WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-153981-20160226174113.patch (text/plain), 65.89 KB, created by
GSkachkov
on 2016-02-26 07:41:32 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
GSkachkov
Created:
2016-02-26 07:41:32 PST
Size:
65.89 KB
patch
obsolete
>Subversion Revision: 197127 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 199f7e153ddbb77d2d9126df611a592c0ea1d32d..827808e277f0225a4fec96e270e7d21674cad9d6 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,87 @@ >+2016-02-26 Skachkov Oleksandr <gskachkov@gmail.com> >+ >+ [ES6] Arrow function syntax. Emit loading&putting this/super only if they are used in arrow function >+ https://bugs.webkit.org/show_bug.cgi?id=153981 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ In first iteration of implemenation arrow function, we emit load and store variables 'this', 'arguments', >+ 'super', 'new.target' in case if arrow function is exist even variables are not used in arrow function. >+ Current patch added logic that prevent from emiting those varibles if they are not used in arrow function. >+ During syntax analyze parser store information about using variables in arrow function inside of >+ the ordinary function scope and then put to BytecodeGenerator through UnlinkedCodeBlock >+ >+ * bytecode/UnlinkedCodeBlock.h: >+ * bytecompiler/BytecodeGenerator.cpp: >+ (JSC::BytecodeGenerator::BytecodeGenerator): >+ (JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded): >+ (JSC::BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment): >+ (JSC::BytecodeGenerator::emitLoadThisFromArrowFunctionLexicalEnvironment): >+ (JSC::BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironment): >+ (JSC::BytecodeGenerator::emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment): >+ (JSC::BytecodeGenerator::isThisUsedInInnerArrowFunction): >+ (JSC::BytecodeGenerator::isArgumentsUsedInInnerArrowFunction): >+ (JSC::BytecodeGenerator::isNewTargetUsedInInnerArrowFunction): >+ (JSC::BytecodeGenerator::isSuperUsedInInnerArrowFunction): >+ (JSC::BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope): >+ (JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope): >+ (JSC::BytecodeGenerator::emitPutThisToArrowFunctionContextScope): >+ * bytecompiler/BytecodeGenerator.h: >+ * bytecompiler/NodesCodegen.cpp: >+ (JSC::ThisNode::emitBytecode): >+ (JSC::EvalFunctionCallNode::emitBytecode): >+ (JSC::FunctionCallValueNode::emitBytecode): >+ (JSC::FunctionNode::emitBytecode): >+ * parser/Nodes.cpp: >+ (JSC::ScopeNode::ScopeNode): >+ (JSC::ProgramNode::ProgramNode): >+ (JSC::ModuleProgramNode::ModuleProgramNode): >+ (JSC::EvalNode::EvalNode): >+ (JSC::FunctionNode::FunctionNode): >+ * parser/Nodes.h: >+ (JSC::ScopeNode::arrowFunctionCodeFeatures): >+ (JSC::ScopeNode::doAnyInnerArrowFunctionsUseArguments): >+ (JSC::ScopeNode::doAnyInnerArrowFunctionsUseSuperCall): >+ (JSC::ScopeNode::doAnyInnerArrowFunctionsUseSuperProperty): >+ (JSC::ScopeNode::doAnyInnerArrowFunctionsUseEval): >+ (JSC::ScopeNode::doAnyInnerArrowFunctionsUseThis): >+ (JSC::ScopeNode::doAnyInnerArrowFunctionsUseNewTarget): >+ * parser/Parser.cpp: >+ (JSC::Parser<LexerType>::parseProperty): >+ (JSC::Parser<LexerType>::parsePrimaryExpression): >+ (JSC::Parser<LexerType>::parseMemberExpression): >+ * parser/Parser.h: >+ (JSC::Scope::Scope): >+ (JSC::Scope::isArrowFunctionBoundary): >+ (JSC::Scope::innerArrowFunctionFeatures): >+ (JSC::Scope::setInnerArrowFunctionUseSuperCall): >+ (JSC::Scope::setInnerArrowFunctionUseSuperProperty): >+ (JSC::Scope::setInnerArrowFunctionUseEval): >+ (JSC::Scope::setInnerArrowFunctionUseThis): >+ (JSC::Scope::setInnerArrowFunctionUseNewTarget): >+ (JSC::Scope::setInnerArrowFunctionUseArguments): >+ (JSC::Scope::setInnerArrowFunctionUseEvalAndUseArgumentsIfNeeded): >+ (JSC::Scope::collectFreeVariables): >+ (JSC::Scope::mergeInnerArrowFunctionFeatures): >+ (JSC::Scope::fillParametersForSourceProviderCache): >+ (JSC::Scope::restoreFromSourceProviderCache): >+ (JSC::Scope::setIsFunction): >+ (JSC::Scope::setIsArrowFunction): >+ (JSC::Parser::closestParentNonArrowFunctionNonLexicalScope): >+ (JSC::Parser::pushScope): >+ (JSC::Parser::popScopeInternal): >+ (JSC::Parser<LexerType>::parse): >+ * parser/ParserModes.h: >+ * parser/SourceProviderCacheItem.h: >+ (JSC::SourceProviderCacheItem::SourceProviderCacheItem): >+ * parser/SyntaxChecker.h: >+ (JSC::SyntaxChecker::createFunctionMetadata): >+ * tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js: >+ * tests/stress/arrowfunction-lexical-bind-arguments-strict.js: >+ * tests/stress/arrowfunction-lexical-bind-newtarget.js: >+ * tests/stress/arrowfunction-lexical-bind-superproperty.js: >+ * tests/stress/arrowfunction-lexical-bind-this-8.js: Added. >+ > 2016-02-24 Joseph Pecoraro <pecoraro@apple.com> > > Web Inspector: Expose Proxy target and handler internal properties to Inspector >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index ae8b4762c6ea6b35bf7e02d44ef6dd4fec032fd6..4580fa3627a9c0672764e894ff081eabdf4a61c0 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -243,7 +243,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke > bool shouldCaptureSomeOfTheThings = m_shouldEmitDebugHooks || functionNode->needsActivation() || containsArrowOrEvalButNotInArrowBlock; > > bool shouldCaptureAllOfTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval(); >- bool needsArguments = (functionNode->usesArguments() || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction())); >+ bool needsArguments = (functionNode->usesArguments() || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction() && isArgumentsUsedInInnerArrowFunction())); > > // Generator never provides "arguments". "arguments" reference will be resolved in an upper generator function scope. > if (parseMode == SourceParseMode::GeneratorBodyMode) >@@ -572,7 +572,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke > // Loading |this| inside an arrow function must be done after initializeDefaultParameterValuesAndSetupFunctionScopeStack() > // because that function sets up the SymbolTable stack and emitLoadThisFromArrowFunctionLexicalEnvironment() > // consults the SymbolTable stack >- if (SourceParseMode::ArrowFunctionMode == parseMode && (functionNode->usesThis() || isDerivedClassContext() || isDerivedConstructorContext())) >+ if (SourceParseMode::ArrowFunctionMode == parseMode && (functionNode->usesThis() || isThisUsedInInnerArrowFunction())) > emitLoadThisFromArrowFunctionLexicalEnvironment(); > > if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunction()) { >@@ -888,16 +888,18 @@ void BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded(SymbolTable* > > if (!m_codeBlock->isArrowFunction()) { > ScopeOffset offset; >+ >+ if (isThisUsedInInnerArrowFunction()) { >+ offset = symbolTable->takeNextScopeOffset(); >+ symbolTable->set(propertyNames().thisIdentifier.impl(), SymbolTableEntry(VarOffset(offset))); >+ } > >- offset = symbolTable->takeNextScopeOffset(); >- symbolTable->set(propertyNames().thisIdentifier.impl(), SymbolTableEntry(VarOffset(offset))); >- >- if (m_codeType == FunctionCode) { >+ if (m_codeType == FunctionCode && isNewTargetUsedInInnerArrowFunction()) { > offset = symbolTable->takeNextScopeOffset(); > symbolTable->set(propertyNames().newTargetLocalPrivateName.impl(), SymbolTableEntry(VarOffset(offset))); > } > >- if (isConstructor() && constructorKind() == ConstructorKind::Derived) { >+ if (isConstructor() && constructorKind() == ConstructorKind::Derived && isSuperUsedInInnerArrowFunction()) { > offset = symbolTable->takeNextScopeOffset(); > symbolTable->set(propertyNames().derivedConstructorPrivateName.impl(), SymbolTableEntry(VarOffset(offset))); > } >@@ -907,28 +909,33 @@ void BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded(SymbolTable* > } > > VariableEnvironment environment; >- auto addResult = environment.add(propertyNames().thisIdentifier); >- addResult.iterator->value.setIsCaptured(); >- addResult.iterator->value.setIsConst(); >+ >+ if (isThisUsedInInnerArrowFunction()) { >+ auto addResult = environment.add(propertyNames().thisIdentifier); >+ addResult.iterator->value.setIsCaptured(); >+ addResult.iterator->value.setIsConst(); >+ } > >- if (m_codeType == FunctionCode) { >+ if (m_codeType == FunctionCode && isNewTargetUsedInInnerArrowFunction()) { > auto addTarget = environment.add(propertyNames().newTargetLocalPrivateName); > addTarget.iterator->value.setIsCaptured(); > addTarget.iterator->value.setIsLet(); > } > >- if (isConstructor() && constructorKind() == ConstructorKind::Derived) { >+ if (isConstructor() && constructorKind() == ConstructorKind::Derived && isSuperUsedInInnerArrowFunction()) { > auto derivedConstructor = environment.add(propertyNames().derivedConstructorPrivateName); > derivedConstructor.iterator->value.setIsCaptured(); > derivedConstructor.iterator->value.setIsLet(); > } > >- size_t size = m_symbolTableStack.size(); >- pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block); >+ if (environment.size() > 0) { >+ size_t size = m_symbolTableStack.size(); >+ pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block); > >- ASSERT_UNUSED(size, m_symbolTableStack.size() == size + 1); >+ ASSERT_UNUSED(size, m_symbolTableStack.size() == size + 1); > >- m_arrowFunctionContextLexicalEnvironmentRegister = m_symbolTableStack.last().m_scope; >+ m_arrowFunctionContextLexicalEnvironmentRegister = m_symbolTableStack.last().m_scope; >+ } > } > > RegisterID* BytecodeGenerator::initializeNextParameter() >@@ -4000,16 +4007,16 @@ void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister) > m_forInContextStack.removeLast(); > } > >-RegisterID* BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment() >+RegisterID* BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment(const Identifier& identifier) > { > ASSERT(m_codeBlock->isArrowFunction() || m_codeBlock->isArrowFunctionContext() || constructorKind() == ConstructorKind::Derived); > >- return emitResolveScope(nullptr, variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped)); >+ return emitResolveScope(nullptr, variable(identifier, ThisResolutionType::Scoped)); > } > > void BytecodeGenerator::emitLoadThisFromArrowFunctionLexicalEnvironment() > { >- emitGetFromScope(thisRegister(), emitLoadArrowFunctionLexicalEnvironment(), variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped), DoNotThrowIfNotFound); >+ emitGetFromScope(thisRegister(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().thisIdentifier), variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped), DoNotThrowIfNotFound); > } > > RegisterID* BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironment() >@@ -4017,7 +4024,7 @@ RegisterID* BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironm > m_isNewTargetLoadedInArrowFunction = true; > > Variable newTargetVar = variable(propertyNames().newTargetLocalPrivateName); >- emitMove(m_newTargetRegister, emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(), newTargetVar, ThrowIfNotFound)); >+ emitMove(m_newTargetRegister, emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().newTargetLocalPrivateName), newTargetVar, ThrowIfNotFound)); > > return m_newTargetRegister; > } >@@ -4025,35 +4032,61 @@ RegisterID* BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironm > RegisterID* BytecodeGenerator::emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment() > { > Variable protoScopeVar = variable(propertyNames().derivedConstructorPrivateName); >- return emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(), protoScopeVar, ThrowIfNotFound); >+ return emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().derivedConstructorPrivateName), protoScopeVar, ThrowIfNotFound); > } > >+bool BytecodeGenerator::isThisUsedInInnerArrowFunction() >+{ >+ return m_scopeNode->doAnyInnerArrowFunctionsUseThis() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval(); >+} >+ >+bool BytecodeGenerator::isArgumentsUsedInInnerArrowFunction() >+{ >+ return m_scopeNode->doAnyInnerArrowFunctionsUseArguments() || m_scopeNode->doAnyInnerArrowFunctionsUseEval(); >+} >+ >+bool BytecodeGenerator::isNewTargetUsedInInnerArrowFunction() >+{ >+ return m_scopeNode->doAnyInnerArrowFunctionsUseNewTarget() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall(); >+} >+ >+bool BytecodeGenerator::isSuperUsedInInnerArrowFunction() >+{ >+ return m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty(); >+} >+ > void BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope() > { >- ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister != nullptr); >+ if (isNewTargetUsedInInnerArrowFunction()) { >+ ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister); > >- Variable newTargetVar = variable(propertyNames().newTargetLocalPrivateName); >- emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, newTargetVar, newTarget(), DoNotThrowIfNotFound, Initialization); >+ Variable newTargetVar = variable(propertyNames().newTargetLocalPrivateName); >+ emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, newTargetVar, newTarget(), DoNotThrowIfNotFound, Initialization); >+ } > } > > void BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope() > { > if ((isConstructor() && constructorKind() == ConstructorKind::Derived) || m_codeBlock->isClassContext()) { >- ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister); >+ if (isSuperUsedInInnerArrowFunction()) { >+ ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister); > >- Variable protoScope = variable(propertyNames().derivedConstructorPrivateName); >- emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, protoScope, &m_calleeRegister, DoNotThrowIfNotFound, Initialization); >+ Variable protoScope = variable(propertyNames().derivedConstructorPrivateName); >+ emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, protoScope, &m_calleeRegister, DoNotThrowIfNotFound, Initialization); >+ } > } > } > > void BytecodeGenerator::emitPutThisToArrowFunctionContextScope() > { >- ASSERT(isDerivedConstructorContext() || m_arrowFunctionContextLexicalEnvironmentRegister != nullptr); >+ if (isThisUsedInInnerArrowFunction()) { >+ ASSERT(isDerivedConstructorContext() || m_arrowFunctionContextLexicalEnvironmentRegister != nullptr); > >- Variable thisVar = variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped); >- RegisterID* scope = isDerivedConstructorContext() ? emitLoadArrowFunctionLexicalEnvironment() : m_arrowFunctionContextLexicalEnvironmentRegister; >+ Variable thisVar = variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped); >+ RegisterID* scope = isDerivedConstructorContext() ? emitLoadArrowFunctionLexicalEnvironment(propertyNames().thisIdentifier) : m_arrowFunctionContextLexicalEnvironmentRegister; > >- emitPutToScope(scope, thisVar, thisRegister(), DoNotThrowIfNotFound, NotInitialization); >+ emitPutToScope(scope, thisVar, thisRegister(), ThrowIfNotFound, NotInitialization); >+ } > } > > void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister) >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >index f2c7ac5c1ba2ffafef358e9836955254b62911a6..5f8ba1e0f9e054155af26b7ce2ca0cf5d9d10fc7 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >@@ -494,7 +494,7 @@ namespace JSC { > > void emitProfileControlFlow(int); > >- RegisterID* emitLoadArrowFunctionLexicalEnvironment(); >+ RegisterID* emitLoadArrowFunctionLexicalEnvironment(const Identifier&); > void emitLoadThisFromArrowFunctionLexicalEnvironment(); > RegisterID* emitLoadNewTargetFromArrowFunctionLexicalEnvironment(); > >@@ -717,8 +717,13 @@ namespace JSC { > RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope); > void emitPushFunctionNameScope(const Identifier& property, RegisterID* value, bool isCaptured); > void emitNewFunctionExpressionCommon(RegisterID*, BaseFuncExprNode*); >+ >+ bool isNewTargetUsedInInnerArrowFunction(); >+ bool isSuperUsedInInnerArrowFunction(); >+ bool isArgumentsUsedInInnerArrowFunction(); > > public: >+ bool isThisUsedInInnerArrowFunction(); > void pushLexicalScope(VariableEnvironmentNode*, TDZCheckOptimization, NestedScopeType = NestedScopeType::IsNotNested, RegisterID** constantSymbolTableResult = nullptr); > void popLexicalScope(VariableEnvironmentNode*); > void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable); >diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >index 06d1148610288637d1ba4b12d3cb0f3471d10097..c1d9546e95956e4998eb5b604d2a3334ffebac7d 100644 >--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >@@ -146,7 +146,7 @@ RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d > > RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) > { >- if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext()) >+ if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction()) > generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); > > if (m_shouldAlwaysEmitTDZCheck || generator.constructorKind() == ConstructorKind::Derived || generator.isDerivedConstructorContext()) >@@ -723,7 +723,7 @@ RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, Reg > // eval("this.id = 'B'"); > // } > // } >- if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext()) >+ if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction()) > generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); > > Variable var = generator.variable(generator.propertyNames().eval); >@@ -3138,7 +3138,7 @@ void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) > > // If there is no return we must automatically insert one. > if (!returnNode) { >- if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext()) >+ if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction()) > generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment > > RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined()); >diff --git a/Source/JavaScriptCore/parser/Nodes.cpp b/Source/JavaScriptCore/parser/Nodes.cpp >index 2557544945b4df3305408198636f1b3a8dd9592d..238a5342eb1c22fe56b4379fd3012a0356fcc26b 100644 >--- a/Source/JavaScriptCore/parser/Nodes.cpp >+++ b/Source/JavaScriptCore/parser/Nodes.cpp >@@ -88,12 +88,13 @@ ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocat > , m_startStartOffset(startLocation.startOffset) > , m_startLineStartOffset(startLocation.lineStartOffset) > , m_features(inStrictContext ? StrictModeFeature : NoFeatures) >+ , m_arrowFunctionCodeFeatures(NoArrowFunctionFeatures) > , m_numConstants(0) > , m_statements(0) > { > } > >-ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, CodeFeatures features, int numConstants) >+ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, CodeFeatures features, ArrowFunctionCodeFeatures arrowFunctionCodeFeatures, int numConstants) > : StatementNode(endLocation) > , ParserArenaRoot(parserArena) > , VariableEnvironmentNode(lexicalVariables) >@@ -101,6 +102,7 @@ ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocat > , m_startStartOffset(startLocation.startOffset) > , m_startLineStartOffset(startLocation.lineStartOffset) > , m_features(features) >+ , m_arrowFunctionCodeFeatures(arrowFunctionCodeFeatures) > , m_source(source) > , m_numConstants(numConstants) > , m_statements(children) >@@ -116,8 +118,8 @@ StatementNode* ScopeNode::singleStatement() const > > // ------------------------------ ProgramNode ----------------------------- > >-ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters*, const SourceCode& source, CodeFeatures features, int numConstants) >- : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, numConstants) >+ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters*, const SourceCode& source, CodeFeatures features, ArrowFunctionCodeFeatures arrowFunctionCodeFeatures, int numConstants) >+ : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, arrowFunctionCodeFeatures, numConstants) > , m_startColumn(startColumn) > , m_endColumn(endColumn) > { >@@ -125,8 +127,8 @@ ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startL > > // ------------------------------ ModuleProgramNode ----------------------------- > >-ModuleProgramNode::ModuleProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters*, const SourceCode& source, CodeFeatures features, int numConstants) >- : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, numConstants) >+ModuleProgramNode::ModuleProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters*, const SourceCode& source, CodeFeatures features, ArrowFunctionCodeFeatures arrowFunctionCodeFeatures, int numConstants) >+ : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, arrowFunctionCodeFeatures, numConstants) > , m_startColumn(startColumn) > , m_endColumn(endColumn) > { >@@ -134,8 +136,8 @@ ModuleProgramNode::ModuleProgramNode(ParserArena& parserArena, const JSTokenLoca > > // ------------------------------ EvalNode ----------------------------- > >-EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters*, const SourceCode& source, CodeFeatures features, int numConstants) >- : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, numConstants) >+EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters*, const SourceCode& source, CodeFeatures features, ArrowFunctionCodeFeatures arrowFunctionCodeFeatures, int numConstants) >+ : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, arrowFunctionCodeFeatures, numConstants) > , m_endColumn(endColumn) > { > } >@@ -180,8 +182,8 @@ void FunctionMetadataNode::setEndPosition(JSTextPosition position) > > // ------------------------------ FunctionNode ----------------------------- > >-FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, int numConstants) >- : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, funcStack, lexicalVariables, features, numConstants) >+FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack& funcStack, VariableEnvironment& lexicalVariables, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, ArrowFunctionCodeFeatures arrowFunctionCodeFeatures, int numConstants) >+ : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, funcStack, lexicalVariables, features, arrowFunctionCodeFeatures, numConstants) > , m_parameters(parameters) > , m_startColumn(startColumn) > , m_endColumn(endColumn) >diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h >index 53519db6d7aa5616899fdefbda91cbd648f7b88f..d7c705f69c142677ada90d6ca16a6c761786b1b7 100644 >--- a/Source/JavaScriptCore/parser/Nodes.h >+++ b/Source/JavaScriptCore/parser/Nodes.h >@@ -1554,7 +1554,7 @@ namespace JSC { > typedef DeclarationStacks::FunctionStack FunctionStack; > > ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, bool inStrictContext); >- ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, CodeFeatures, int numConstants); >+ ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, CodeFeatures, ArrowFunctionCodeFeatures, int numConstants); > > using ParserArenaRoot::operator new; > >@@ -1568,6 +1568,13 @@ namespace JSC { > > void setFeatures(CodeFeatures features) { m_features = features; } > CodeFeatures features() { return m_features; } >+ ArrowFunctionCodeFeatures arrowFunctionCodeFeatures() { return m_arrowFunctionCodeFeatures; } >+ bool doAnyInnerArrowFunctionsUseArguments() { return m_arrowFunctionCodeFeatures & ArgumentsArrowFunctionFeature; } >+ bool doAnyInnerArrowFunctionsUseSuperCall() { return m_arrowFunctionCodeFeatures & SuperCallArrowFunctionFeature; } >+ bool doAnyInnerArrowFunctionsUseSuperProperty() { return m_arrowFunctionCodeFeatures & SuperPropertyArrowFunctionFeature; } >+ bool doAnyInnerArrowFunctionsUseEval() { return m_arrowFunctionCodeFeatures & EvalArrowFunctionFeature; } >+ bool doAnyInnerArrowFunctionsUseThis() { return m_arrowFunctionCodeFeatures & ThisArrowFunctionFeature; } >+ bool doAnyInnerArrowFunctionsUseNewTarget() { return m_arrowFunctionCodeFeatures & NewTargetArrowFunctionFeature; } > > bool usesEval() const { return m_features & EvalFeature; } > bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); } >@@ -1605,6 +1612,7 @@ namespace JSC { > > private: > CodeFeatures m_features; >+ ArrowFunctionCodeFeatures m_arrowFunctionCodeFeatures; > SourceCode m_source; > VariableEnvironment m_varDeclarations; > FunctionStack m_functionStack; >@@ -1614,7 +1622,7 @@ namespace JSC { > > class ProgramNode : public ScopeNode { > public: >- ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, FunctionParameters*, const SourceCode&, CodeFeatures, int numConstants); >+ ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, FunctionParameters*, const SourceCode&, CodeFeatures, ArrowFunctionCodeFeatures, int numConstants); > > unsigned startColumn() const { return m_startColumn; } > unsigned endColumn() const { return m_endColumn; } >@@ -1629,7 +1637,7 @@ namespace JSC { > > class EvalNode : public ScopeNode { > public: >- EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, FunctionParameters*, const SourceCode&, CodeFeatures, int numConstants); >+ EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, FunctionParameters*, const SourceCode&, CodeFeatures, ArrowFunctionCodeFeatures, int numConstants); > > ALWAYS_INLINE unsigned startColumn() const { return 0; } > unsigned endColumn() const { return m_endColumn; } >@@ -1644,7 +1652,7 @@ namespace JSC { > > class ModuleProgramNode : public ScopeNode { > public: >- ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, FunctionParameters*, const SourceCode&, CodeFeatures, int numConstants); >+ ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, FunctionParameters*, const SourceCode&, CodeFeatures, ArrowFunctionCodeFeatures, int numConstants); > > unsigned startColumn() const { return m_startColumn; } > unsigned endColumn() const { return m_endColumn; } >@@ -1883,7 +1891,7 @@ namespace JSC { > > class FunctionNode final : public ScopeNode { > public: >- FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, FunctionParameters*, const SourceCode&, CodeFeatures, int numConstants); >+ FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&, VariableEnvironment&, FunctionParameters*, const SourceCode&, CodeFeatures, ArrowFunctionCodeFeatures, int numConstants); > > FunctionParameters* parameters() const { return m_parameters; } > >diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp >index c66b74282a7d6130c33592da0a2058f733e9c889..36e7e80697b166b687c4c10f73dc498f1a89db4d 100644 >--- a/Source/JavaScriptCore/parser/Parser.cpp >+++ b/Source/JavaScriptCore/parser/Parser.cpp >@@ -3207,6 +3207,8 @@ template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeB > JSTextPosition start = tokenStartPosition(); > JSTokenLocation location(tokenLocation()); > currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident); >+ if (currentScope()->isArrowFunction()) >+ currentScope()->setInnerArrowFunctionUseEval(); > TreeExpression node = context.createResolve(location, *ident, start, lastTokenEndPosition()); > return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete); > } >@@ -3620,6 +3622,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre > case THISTOKEN: { > JSTokenLocation location(tokenLocation()); > next(); >+ if (currentScope()->isArrowFunction()) >+ currentScope()->setInnerArrowFunctionUseThis(); > return context.createThisExpr(location, m_thisTDZMode); > } > case IDENT: { >@@ -3795,6 +3799,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres > if (m_vm->propertyNames->target == *ident) { > semanticFailIfFalse(currentScope()->isFunction(), "new.target is only valid inside functions"); > baseIsNewTarget = true; >+ if (currentScope()->isArrowFunction()) >+ currentScope()->setInnerArrowFunctionUseNewTarget(); > base = context.createNewTargetExpr(location); > newCount--; > next(); >@@ -3873,6 +3879,15 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres > default: > goto endMemberExpression; > } >+ >+ if (currentFunctionScope()->isArrowFunction()) { >+ if (currentFunctionScope()->hasDirectSuper()) >+ currentFunctionScope()->setInnerArrowFunctionUseSuperCall(); >+ >+ if (currentFunctionScope()->needsSuperBinding()) >+ currentFunctionScope()->setInnerArrowFunctionUseSuperProperty(); >+ } >+ > baseIsSuper = false; > } > endMemberExpression: >diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h >index 02a726a569f47e9fa38fe92037eaeac25c3a8dfc..59c5d0967c7e3a81836ba2246500b7a96c853f37 100644 >--- a/Source/JavaScriptCore/parser/Parser.h >+++ b/Source/JavaScriptCore/parser/Parser.h >@@ -158,7 +158,7 @@ private: > }; > > struct Scope { >- Scope(const VM* vm, bool isFunction, bool isGenerator, bool strictMode) >+ Scope(const VM* vm, bool isFunction, bool isGenerator, bool strictMode, bool isArrowFunction) > : m_vm(vm) > , m_shadowsArguments(false) > , m_usesEval(false) >@@ -170,7 +170,8 @@ struct Scope { > , m_strictMode(strictMode) > , m_isFunction(isFunction) > , m_isGenerator(isGenerator) >- , m_isArrowFunction(false) >+ , m_isArrowFunction(isArrowFunction) >+ , m_isArrowFunctionBoundary(false) > , m_isLexicalScope(false) > , m_isFunctionBoundary(false) > , m_isValidStrictMode(true) >@@ -179,6 +180,7 @@ struct Scope { > , m_expectedSuperBinding(static_cast<unsigned>(SuperBinding::NotNeeded)) > , m_loopDepth(0) > , m_switchDepth(0) >+ , m_innerArrowFunctionFeatures(0) > { > } > >@@ -195,6 +197,7 @@ struct Scope { > , m_isFunction(rhs.m_isFunction) > , m_isGenerator(rhs.m_isGenerator) > , m_isArrowFunction(rhs.m_isArrowFunction) >+ , m_isArrowFunctionBoundary(rhs.m_isArrowFunctionBoundary) > , m_isLexicalScope(rhs.m_isLexicalScope) > , m_isFunctionBoundary(rhs.m_isFunctionBoundary) > , m_isValidStrictMode(rhs.m_isValidStrictMode) >@@ -203,6 +206,7 @@ struct Scope { > , m_expectedSuperBinding(rhs.m_expectedSuperBinding) > , m_loopDepth(rhs.m_loopDepth) > , m_switchDepth(rhs.m_switchDepth) >+ , m_innerArrowFunctionFeatures(rhs.m_innerArrowFunctionFeatures) > , m_moduleScopeData(rhs.m_moduleScopeData) > { > if (rhs.m_labels) { >@@ -465,6 +469,7 @@ struct Scope { > > void setNeedsFullActivation() { m_needsFullActivation = true; } > bool needsFullActivation() const { return m_needsFullActivation; } >+ bool isArrowFunctionBoundary() { return m_isArrowFunctionBoundary; } > bool isArrowFunction() { return m_isArrowFunction; } > > bool hasDirectSuper() { return m_hasDirectSuper; } >@@ -473,11 +478,31 @@ struct Scope { > bool needsSuperBinding() { return m_needsSuperBinding; } > void setNeedsSuperBinding() { m_needsSuperBinding = true; } > >+ ArrowFunctionCodeFeatures innerArrowFunctionFeatures() { return m_innerArrowFunctionFeatures; } >+ > void setExpectedSuperBinding(SuperBinding superBinding) { m_expectedSuperBinding = static_cast<unsigned>(superBinding); } > SuperBinding expectedSuperBinding() const { return static_cast<SuperBinding>(m_expectedSuperBinding); } > void setConstructorKind(ConstructorKind constructorKind) { m_constructorKind = static_cast<unsigned>(constructorKind); } > ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); } > >+ void setInnerArrowFunctionUseSuperCall() { m_innerArrowFunctionFeatures |= SuperCallArrowFunctionFeature; } >+ void setInnerArrowFunctionUseSuperProperty() { m_innerArrowFunctionFeatures |= SuperPropertyArrowFunctionFeature; } >+ void setInnerArrowFunctionUseEval() { m_innerArrowFunctionFeatures |= EvalArrowFunctionFeature; } >+ void setInnerArrowFunctionUseThis() { m_innerArrowFunctionFeatures |= ThisArrowFunctionFeature; } >+ void setInnerArrowFunctionUseNewTarget() { m_innerArrowFunctionFeatures |= NewTargetArrowFunctionFeature; } >+ void setInnerArrowFunctionUseArguments() { m_innerArrowFunctionFeatures |= ArgumentsArrowFunctionFeature; } >+ >+ void setInnerArrowFunctionUseEvalAndUseArgumentsIfNeeded() >+ { >+ ASSERT(m_isArrowFunction); >+ >+ if (m_usesEval) >+ setInnerArrowFunctionUseEval(); >+ >+ if (m_usedVariables.contains(m_vm->propertyNames->arguments.impl())) >+ setInnerArrowFunctionUseArguments(); >+ } >+ > void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) > { > if (nestedScope->m_usesEval) >@@ -489,7 +514,7 @@ struct Scope { > continue; > > // "arguments" reference should be resolved at function boudary. >- if (nestedScope->isFunctionBoundary() && nestedScope->hasArguments() && impl == m_vm->propertyNames->arguments.impl() && !nestedScope->isArrowFunction()) >+ if (nestedScope->isFunctionBoundary() && nestedScope->hasArguments() && impl == m_vm->propertyNames->arguments.impl() && !nestedScope->isArrowFunctionBoundary()) > continue; > > m_usedVariables.add(impl); >@@ -518,6 +543,11 @@ struct Scope { > } > } > >+ void mergeInnerArrowFunctionFeatures(ArrowFunctionCodeFeatures arrowFunctionCodeFeatures) >+ { >+ m_innerArrowFunctionFeatures = m_innerArrowFunctionFeatures | arrowFunctionCodeFeatures; >+ } >+ > void getCapturedVars(IdentifierSet& capturedVariables, bool& modifiedParameter, bool& modifiedArguments) > { > if (m_needsFullActivation || m_usesEval) { >@@ -568,6 +598,7 @@ struct Scope { > parameters.usesEval = m_usesEval; > parameters.strictMode = m_strictMode; > parameters.needsFullActivation = m_needsFullActivation; >+ parameters.innerArrowFunctionFeatures = m_innerArrowFunctionFeatures; > copyCapturedVariablesToVector(m_writtenVariables, parameters.writtenVariables); > copyCapturedVariablesToVector(m_usedVariables, parameters.usedVariables); > } >@@ -577,6 +608,7 @@ struct Scope { > ASSERT(m_isFunction); > m_usesEval = info->usesEval; > m_strictMode = info->strictMode; >+ m_innerArrowFunctionFeatures = info->innerArrowFunctionFeatures; > m_needsFullActivation = info->needsFullActivation; > for (unsigned i = 0; i < info->usedVariablesCount; ++i) > m_usedVariables.add(info->usedVariables()[i]); >@@ -592,6 +624,8 @@ private: > m_hasArguments = true; > setIsLexicalScope(); > m_isGenerator = false; >+ m_isArrowFunctionBoundary = false; >+ m_isArrowFunction = false; > } > > void setIsGeneratorFunction() >@@ -610,6 +644,7 @@ private: > void setIsArrowFunction() > { > setIsFunction(); >+ m_isArrowFunctionBoundary = true; > m_isArrowFunction = true; > } > >@@ -630,6 +665,7 @@ private: > bool m_isFunction : 1; > bool m_isGenerator : 1; > bool m_isArrowFunction : 1; >+ bool m_isArrowFunctionBoundary : 1; > bool m_isLexicalScope : 1; > bool m_isFunctionBoundary : 1; > bool m_isValidStrictMode : 1; >@@ -638,6 +674,7 @@ private: > unsigned m_expectedSuperBinding : 2; > int m_loopDepth; > int m_switchDepth; >+ ArrowFunctionCodeFeatures m_innerArrowFunctionFeatures; > > typedef Vector<ScopeLabelInfo, 2> LabelStack; > std::unique_ptr<LabelStack> m_labels; >@@ -896,9 +933,8 @@ private: > { > unsigned i = m_scopeStack.size() - 1; > ASSERT(i < m_scopeStack.size() && m_scopeStack.size()); >- while (i && (!m_scopeStack[i].isFunctionBoundary() || m_scopeStack[i].isArrowFunction())) >+ while (i && (!m_scopeStack[i].isFunctionBoundary() || m_scopeStack[i].isArrowFunctionBoundary())) > i--; >- // When reaching the top level scope (it can be non function scope), we return it. > return ScopeRef(&m_scopeStack, i); > } > >@@ -907,12 +943,14 @@ private: > bool isFunction = false; > bool isStrict = false; > bool isGenerator = false; >+ bool isArrowFunction = false; > if (!m_scopeStack.isEmpty()) { > isStrict = m_scopeStack.last().strictMode(); > isFunction = m_scopeStack.last().isFunction(); > isGenerator = m_scopeStack.last().isGenerator(); >+ isArrowFunction = m_scopeStack.last().isArrowFunction(); > } >- m_scopeStack.append(Scope(m_vm, isFunction, isGenerator, isStrict)); >+ m_scopeStack.append(Scope(m_vm, isFunction, isGenerator, isStrict, isArrowFunction)); > return currentScope(); > } > >@@ -921,6 +959,13 @@ private: > 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); >+ >+ if (m_scopeStack.last().isArrowFunction()) >+ m_scopeStack.last().setInnerArrowFunctionUseEvalAndUseArgumentsIfNeeded(); >+ >+ if (!(m_scopeStack.last().isFunctionBoundary() && !m_scopeStack.last().isArrowFunctionBoundary())) >+ m_scopeStack[m_scopeStack.size() - 2].mergeInnerArrowFunctionFeatures(m_scopeStack.last().innerArrowFunctionFeatures()); >+ > if (!m_scopeStack.last().isFunctionBoundary() && m_scopeStack.last().needsFullActivation()) > m_scopeStack[m_scopeStack.size() - 2].setNeedsFullActivation(); > m_scopeStack.removeLast(); >@@ -1497,6 +1542,7 @@ std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const I > m_parameters, > *m_source, > m_features, >+ currentScope()->innerArrowFunctionFeatures(), > m_numConstants); > result->setLoc(m_source->firstLine(), m_lexer->lineNumber(), m_lexer->currentOffset(), m_lexer->currentLineStartOffset()); > result->setEndOffset(m_lexer->currentOffset()); >diff --git a/Source/JavaScriptCore/parser/ParserModes.h b/Source/JavaScriptCore/parser/ParserModes.h >index 4f6bac6c3cdb7d72865be3719360baf834245c23..f07cbb8d004c00c7aedf0d19a007a802ae9f443c 100644 >--- a/Source/JavaScriptCore/parser/ParserModes.h >+++ b/Source/JavaScriptCore/parser/ParserModes.h >@@ -161,6 +161,17 @@ const CodeFeatures ArrowFunctionContextFeature = 1 << 9; > > const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature | ModifiedParameterFeature | ArrowFunctionFeature | ArrowFunctionContextFeature; > >+typedef uint8_t ArrowFunctionCodeFeatures; >+ >+const ArrowFunctionCodeFeatures NoArrowFunctionFeatures = 0; >+const ArrowFunctionCodeFeatures EvalArrowFunctionFeature = 1 << 0; >+const ArrowFunctionCodeFeatures ArgumentsArrowFunctionFeature = 1 << 1; >+const ArrowFunctionCodeFeatures ThisArrowFunctionFeature = 1 << 2; >+const ArrowFunctionCodeFeatures SuperCallArrowFunctionFeature = 1 << 3; >+const ArrowFunctionCodeFeatures SuperPropertyArrowFunctionFeature = 1 << 4; >+const ArrowFunctionCodeFeatures NewTargetArrowFunctionFeature = 1 << 5; >+ >+const ArrowFunctionCodeFeatures AllArrowFunctionCodeFeatures = EvalArrowFunctionFeature | ArgumentsArrowFunctionFeature | ThisArrowFunctionFeature | SuperCallArrowFunctionFeature | SuperPropertyArrowFunctionFeature | NewTargetArrowFunctionFeature; > } // namespace JSC > > #endif // ParserModes_h >diff --git a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h >index 81d221b39610a78136711e3314dabbd82aacd512..0fc4a945fdd4024906e1dad25a6dd4efbbb92592 100644 >--- a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h >+++ b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h >@@ -44,6 +44,7 @@ struct SourceProviderCacheItemCreationParameters { > bool needsFullActivation; > bool usesEval; > bool strictMode; >+ ArrowFunctionCodeFeatures innerArrowFunctionFeatures; > Vector<RefPtr<UniquedStringImpl>> usedVariables; > Vector<RefPtr<UniquedStringImpl>> writtenVariables; > bool isBodyArrowExpression { false }; >@@ -87,6 +88,8 @@ public: > bool usesEval : 1; > > bool strictMode : 1; >+ >+ ArrowFunctionCodeFeatures innerArrowFunctionFeatures; > > unsigned lastTockenLineStartOffset; > unsigned usedVariablesCount; >@@ -127,6 +130,7 @@ inline SourceProviderCacheItem::SourceProviderCacheItem(const SourceProviderCach > , parameterCount(parameters.parameterCount) > , usesEval(parameters.usesEval) > , strictMode(parameters.strictMode) >+ , innerArrowFunctionFeatures(parameters.innerArrowFunctionFeatures) > , lastTockenLineStartOffset(parameters.lastTockenLineStartOffset) > , usedVariablesCount(parameters.usedVariables.size()) > , writtenVariablesCount(parameters.writtenVariables.size()) >diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h >index eed7b8ce3ecc8b888b176cf53681d2109d04f1da..19f6bc8ba88a8cb301e92b9448163b34d5b3e36a 100644 >--- a/Source/JavaScriptCore/parser/SyntaxChecker.h >+++ b/Source/JavaScriptCore/parser/SyntaxChecker.h >@@ -183,7 +183,7 @@ public: > ExpressionType createYield(const JSTokenLocation&, ExpressionType, bool, int, int, int) { return YieldExpr; } > ClassExpression createClassExpr(const JSTokenLocation&, const Identifier&, VariableEnvironment&, ExpressionType, ExpressionType, PropertyList, PropertyList) { return ClassExpr; } > ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; } >- int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool) { return FunctionBodyResult; } >+ int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool, ArrowFunctionCodeFeatures = NoArrowFunctionFeatures) { return FunctionBodyResult; } > ExpressionType createArrowFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; } > void setFunctionNameStart(int, int) { } > int createArguments() { return ArgumentsResult; } >diff --git a/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js >index 2b281ba2878adcc77aa14d8de760bb036e6bd606..bb8ba7a72b1c29ee3977f6d1a036a6d278a89b30 100644 >--- a/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js >+++ b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js >@@ -214,3 +214,39 @@ function boo() { > for (var i = 0; i < 10000; i++) { > testCase(boo('A' + i)('B' + i)('D' + i)('E' + i)('G' + i)[0], 'E' + i, txtMsg + "#17"); > } >+ >+var testValue = 'test-value'; >+ >+function f_args () { >+ if (true) { >+ let someValue = ''; >+ if (true) { >+ let anotherValue = 'value'; >+ return () => () => () => arguments[0]; >+ } >+ } >+ >+ return () => 'no-value'; >+} >+ >+for (var i = 0; i < 10000; i++) { >+ let v = f_args(testValue, 'anotherValue')()()(); >+ testCase(v, testValue); >+} >+ >+function f_args_eval () { >+ if (true) { >+ let someValue = ''; >+ if (true) { >+ let anotherValue = 'value'; >+ return () => () => () => eval('arguments[0]'); >+ } >+ } >+ >+ return () => 'no-value'; >+} >+ >+for (var i = 0; i < 10000; i++) { >+ let v = f_args_eval(testValue, 'anotherValue')()()(); >+ testCase(v, testValue); >+} >diff --git a/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-arguments-strict.js b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-arguments-strict.js >index fd8c9c74ffb3c34c64a311ef3adc181703ff55ed..86ffeff07ae5cda3f6b6bf4a7738b5305739bff5 100644 >--- a/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-arguments-strict.js >+++ b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-arguments-strict.js >@@ -131,3 +131,39 @@ function test() { > } > > test(); >+ >+var testValue = 'test-value'; >+ >+function f_args () { >+ if (true) { >+ let someValue = ''; >+ if (true) { >+ let anotherValue = 'value'; >+ return () => () => () => arguments[0]; >+ } >+ } >+ >+ return () => 'no-value'; >+} >+ >+for (var i = 0; i < 10000; i++) { >+ let v = f_args(testValue, 'anotherValue')()()(); >+ testCase(v, testValue); >+} >+ >+function f_args_eval () { >+ if (true) { >+ let someValue = ''; >+ if (true) { >+ let anotherValue = 'value'; >+ return () => () => () => eval('arguments[0]'); >+ } >+ } >+ >+ return () => 'no-value'; >+} >+ >+for (var i = 0; i < 10000; i++) { >+ let v = f_args_eval(testValue, 'anotherValue')()()(); >+ testCase(v, testValue); >+} >diff --git a/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-newtarget.js b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-newtarget.js >index 7a8d27c1c9a3c09eb5aad26e260a158d4934b2c9..3976260e6b959ad78d1ca364acd68047c9c9c862 100644 >--- a/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-newtarget.js >+++ b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-newtarget.js >@@ -76,3 +76,17 @@ for (var i = 0; i < 1000; i++) { > testCase(tryToCreateClass(true), true, "Error: newTargetLocal should be hided variable"); > testCase(tryToCreateClass(false), true, "Error: newTargetLocal should be hided variable"); > } >+ >+function getTargetBlockScope() { >+ if (true) { >+ let someValue = ''; >+ if (true) >+ return x => new.target; >+ } >+ return ()=>value; >+} >+ >+for (var i = 0; i < 1000; i++) { >+ var undefinedTarget = getTargetBlockScope()() >+ testCase(undefinedTarget, undefined, "Error: new.target is not lexically binded inside of the arrow function #4"); >+} >diff --git a/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-superproperty.js b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-superproperty.js >index a8bad15a82cd7629a4908a9d122270cbbfb0d817..2a1f2b4688dbd90af5e6b6a9cef875b3a2499c9c 100644 >--- a/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-superproperty.js >+++ b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-superproperty.js >@@ -123,6 +123,20 @@ var G = class G extends A { > getParentValue() { > return super.getValue(); > } >+ >+ getValueBlockScope() { >+ if (true) { >+ var someValue =''; >+ if (true) { >+ return () => { >+ if (true) { >+ let internalValue = ''; >+ return super.getValue(); >+ } >+ } >+ } >+ } >+ } > }; > > var g = new G(); >@@ -141,6 +155,8 @@ for (var i = 0; i < 10000; i++) { > let setValue = g1.setValueCB(); > setValue('new-value'); > testCase(getValue(), 'new-value', 'Error: Some problem with using arrow and "super" inside of the method that retun arrow function'); >+ getValue = g1.getValueBlockScope(); >+ testCase(getValue(), 'new-value', 'Error: Some problem with using arrow and "super" with deep nesting inside of the method that retun arrow function'); > } > > var H = class H extends A { >diff --git a/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-this-8.js b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-this-8.js >new file mode 100644 >index 0000000000000000000000000000000000000000..8a497a008acdabaf81884d54c1fc1f85a18bebf0 >--- /dev/null >+++ b/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-this-8.js >@@ -0,0 +1,104 @@ >+var testCase = function (actual, expected, message) { >+ if (actual !== expected) { >+ throw message + ". Expected '" + expected + "', but was '" + actual + "'"; >+ } >+}; >+ >+let testValue = 'test-value'; >+ >+var f_this = function () { >+ let value = 'value'; >+ if (true) { >+ let someValue = 'someValue'; >+ if (true) { >+ let = anotherValue = 'value'; >+ return () => () => () => this.value; >+ } >+ } >+ >+ return () => value; >+} >+ >+for (let i = 0; i < 10000; i++) { >+ testCase(f_this.call({value : testValue})()()(), testValue); >+} >+ >+var f_this_eval = function () { >+ if (true) { >+ let someValue = ''; >+ if (true) { >+ let = anotherValue = 'value'; >+ return () => () => () => eval('this.value'); >+ } >+ } >+ >+ return () => 'no-value'; >+} >+ >+for (let i = 0; i < 10000; i++) { >+ testCase(f_this_eval.call({value : testValue}, false)()()(), testValue); >+} >+ >+ >+function f_this_branches (branch, returnThis) { >+ let value = 'value'; >+ if (branch === 'A') { >+ let someValue = 'someValue'; >+ if (true) { >+ let = anotherValue = 'value'; >+ return () => () => () => { >+ if (returnThis) >+ return this.value; >+ else >+ return anotherValue; >+ } >+ } >+ } >+ >+ return () => value; >+} >+ >+for (let i = 0; i < 10000; i++) { >+ testCase(f_this_branches.call({value : testValue}, 'B')() == testValue, false); >+ testCase(f_this_branches.call({value : testValue}, 'A', false)()()() == testValue, false); >+ testCase(f_this_branches.call({value : testValue}, 'A', true)()()(), testValue); >+} >+ >+function f_this_eval_branches (branch, returnThis) { >+ let value = 'value'; >+ if (branch === 'A') { >+ let someValue = 'someValue'; >+ if (true) { >+ let = anotherValue = 'value'; >+ return () => () => () => { >+ if (returnThis) >+ return eval('this.value'); >+ else >+ return anotherValue; >+ } >+ } >+ } >+ >+ return () => value; >+} >+ >+for (let i = 0; i < 10000; i++) { >+ testCase(f_this_eval_branches.call({value : testValue}, 'B')() == testValue, false); >+ testCase(f_this_eval_branches.call({value : testValue}, 'A', false)()()() == testValue, false); >+ testCase(f_this_eval_branches.call({value : testValue}, 'A', true)()()(), testValue); >+} >+ >+let self = this; >+ >+let arrow = () => { >+ testCase(self, this, "Error: Wrong lexical bind of this"); >+}; >+ >+for (let i = 0; i < 10000; i++) { >+ arrow(); >+} >+ >+ >+for (let i = 0; i < 10000; i++) { >+ eval("let _self=this;(()=>testCase(self, this, 'Error: Wrong lexical bind of this in eval'))();"); >+} >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 4969e2ca1637583fc1f132d9d9f2ffe9edb7e286..8a55e5f2709cdeb9c4d4f78e7c4d0da234d4146a 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,23 @@ >+2016-02-26 Skachkov Oleksandr <gskachkov@gmail.com> >+ >+ [ES6] Arrow function syntax. Emit loading&putting this/super only if they are used in arrow function >+ https://bugs.webkit.org/show_bug.cgi?id=153981 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Added new benchmark tests for invoking arrow function within function, class's constructor and method >+ >+ * js/regress/arrowfunction-call-in-class-constructor-expected.txt: Added. >+ * js/regress/arrowfunction-call-in-class-constructor.html: Added. >+ * js/regress/arrowfunction-call-in-class-method-expected.txt: Added. >+ * js/regress/arrowfunction-call-in-class-method.html: Added. >+ * js/regress/arrowfunction-call-in-function-expected.txt: Added. >+ * js/regress/arrowfunction-call-in-function.html: Added. >+ * js/regress/script-tests/arrowfunction-call-in-class-constructor.js: Added. >+ * js/regress/script-tests/arrowfunction-call-in-class-method.js: Added. >+ * js/regress/script-tests/arrowfunction-call-in-function.js: Added. >+ * js/regress/script-tests/arrowfunction-call.js: >+ > 2016-02-25 Ryan Haddad <ryanhaddad@apple.com> > > Removing a pass expectation for inspector/indexeddb/requestDatabaseNames.html that overrides the skip r197122 >diff --git a/LayoutTests/js/regress/arrowfunction-call-in-class-constructor-expected.txt b/LayoutTests/js/regress/arrowfunction-call-in-class-constructor-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..441d06eb59b2f89ae8299f86c2e8ed481c459a4d >--- /dev/null >+++ b/LayoutTests/js/regress/arrowfunction-call-in-class-constructor-expected.txt >@@ -0,0 +1,10 @@ >+JSRegress/arrowfunction-call-in-class-constructor >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS no exception thrown >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/regress/arrowfunction-call-in-class-constructor.html b/LayoutTests/js/regress/arrowfunction-call-in-class-constructor.html >new file mode 100644 >index 0000000000000000000000000000000000000000..51559095273232266bcdd0a2cf08fcb023488e08 >--- /dev/null >+++ b/LayoutTests/js/regress/arrowfunction-call-in-class-constructor.html >@@ -0,0 +1,12 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="../../resources/regress-pre.js"></script> >+<script src="script-tests/arrowfunction-call-in-class-constructor.js"></script> >+<script src="../../resources/regress-post.js"></script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/regress/arrowfunction-call-in-class-method-expected.txt b/LayoutTests/js/regress/arrowfunction-call-in-class-method-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..c602f6d9a24d3b1278597e5dfa572fb54bf8ddcc >--- /dev/null >+++ b/LayoutTests/js/regress/arrowfunction-call-in-class-method-expected.txt >@@ -0,0 +1,10 @@ >+JSRegress/arrowfunction-call-in-class-method >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS no exception thrown >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/regress/arrowfunction-call-in-class-method.html b/LayoutTests/js/regress/arrowfunction-call-in-class-method.html >new file mode 100644 >index 0000000000000000000000000000000000000000..704861b3cc77de4e8c9895c48c107894605cee6a >--- /dev/null >+++ b/LayoutTests/js/regress/arrowfunction-call-in-class-method.html >@@ -0,0 +1,12 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="../../resources/regress-pre.js"></script> >+<script src="script-tests/arrowfunction-call-in-class-method.js"></script> >+<script src="../../resources/regress-post.js"></script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/regress/arrowfunction-call-in-function-expected.txt b/LayoutTests/js/regress/arrowfunction-call-in-function-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..d016302f559e04fb279da14d6a40f1c9105d7acd >--- /dev/null >+++ b/LayoutTests/js/regress/arrowfunction-call-in-function-expected.txt >@@ -0,0 +1,10 @@ >+JSRegress/arrowfunction-call-in-function >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS no exception thrown >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/regress/arrowfunction-call-in-function.html b/LayoutTests/js/regress/arrowfunction-call-in-function.html >new file mode 100644 >index 0000000000000000000000000000000000000000..74c1859106e4959ac1c0485dbb087cf7d33cc4be >--- /dev/null >+++ b/LayoutTests/js/regress/arrowfunction-call-in-function.html >@@ -0,0 +1,12 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="../../resources/regress-pre.js"></script> >+<script src="script-tests/arrowfunction-call-in-function.js"></script> >+<script src="../../resources/regress-post.js"></script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-constructor.js b/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-constructor.js >new file mode 100644 >index 0000000000000000000000000000000000000000..e4d0e8e77cbc6bd3ae5616cbdc16eaafd26032d0 >--- /dev/null >+++ b/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-constructor.js >@@ -0,0 +1,23 @@ >+var testValue = 'test-value'; >+ >+class A { >+ constructor() { >+ this.value = testValue; >+ } >+} >+ >+class B extends A { >+ constructor() { >+ super(); >+ var arrow = () => testValue; >+ arrow(); >+ } >+} >+ >+noInline(B); >+ >+for (let i = 0; i < 1000000; ++i) { >+ let b = new B(); >+ if (b.value != testValue) >+ throw "Error: bad result: " + result; >+} >diff --git a/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-method.js b/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-method.js >new file mode 100644 >index 0000000000000000000000000000000000000000..71c869db4176efe2991ef3f07e5fc6adabe47d87 >--- /dev/null >+++ b/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-method.js >@@ -0,0 +1,24 @@ >+var testValue = 'test-value'; >+ >+class A { >+ constructor() { >+ this.value = testValue; >+ } >+ >+ getValue () { >+ return this.value; >+ } >+} >+ >+class B extends A { >+ getParentValue() { >+ var arrow = () => testValue; >+ return arrow(); >+ } >+} >+ >+for (let i = 0; i < 100000; ++i) { >+ let b = new B(); >+ if (b.getParentValue() != testValue) >+ throw "Error: bad result: " + result; >+} >diff --git a/LayoutTests/js/regress/script-tests/arrowfunction-call-in-function.js b/LayoutTests/js/regress/script-tests/arrowfunction-call-in-function.js >new file mode 100644 >index 0000000000000000000000000000000000000000..03b0bba1d7b4b8b2cca3783612d82a440b92280b >--- /dev/null >+++ b/LayoutTests/js/regress/script-tests/arrowfunction-call-in-function.js >@@ -0,0 +1,11 @@ >+function bar(a, b) { >+ return ((_a, _b) => _a + _b)(a, b); >+} >+ >+noInline(bar); >+ >+for (let i = 0; i < 1000000; ++i) { >+ let result = bar(1, 2); >+ if (result != 3) >+ throw "Error: bad result: " + result; >+} >diff --git a/LayoutTests/js/regress/script-tests/arrowfunction-call.js b/LayoutTests/js/regress/script-tests/arrowfunction-call.js >index 8924c84276e71087786c5940a822bcc6f97c06d7..976bf176c96736314234a601b1d2b46b27cc8c6e 100644 >--- a/LayoutTests/js/regress/script-tests/arrowfunction-call.js >+++ b/LayoutTests/js/regress/script-tests/arrowfunction-call.js >@@ -8,8 +8,8 @@ function bar(a, b) { > > noInline(bar); > >-for (var i = 0; i < 1000000; ++i) { >- var result = bar(1, 2); >+for (let i = 0; i < 1000000; ++i) { >+ let result = bar(1, 2); > if (result != 3) > throw "Error: bad result: " + result; > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 153981
:
271198
|
271327
|
271677
|
271685
|
271811
|
271820
|
271821
|
271823
|
271852
|
271854
|
271939
|
271952
|
272107
|
272326
|
272424
|
272425
|
272456