test262: test262/test/language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js
https://bugs.webkit.org/show_bug.cgi?id=171190
Patch by Joseph Pecoraro <pecoraro@apple.com> on 2017-04-24
Reviewed by Saam Barati.
JSTests:
* stress/async-await-syntax.js:
* test262.yaml:
Source/JavaScriptCore:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitNewFunctionExpressionCommon):
(JSC::BytecodeGenerator::emitNewFunction):
* bytecompiler/NodesCodegen.cpp:
(JSC::FunctionNode::emitBytecode):
(JSC::Scope::setSourceParseMode):
* parser/ParserModes.h:
(JSC::isFunctionParseMode):
(JSC::isMethodParseMode):
(JSC::isGeneratorOrAsyncFunctionWrapperParseMode):
(JSC::isGeneratorParseMode):
(JSC::isGeneratorWrapperParseMode):
* runtime/FunctionExecutable.h:
* runtime/JSFunction.cpp:
(JSC::JSFunction::getOwnPropertySlot):
Add a new GeneratorWrapperMethodMode parse mode. The other function types
(async, arrow) already have a FunctionMode and a MethodMode. Give
generators one as well. This lets isMethodParseMode actually be accurate.
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::isArrowFunctionParameters):
(JSC::Parser<LexerType>::parseFormalParameters):
(JSC::stringForFunctionMode):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseFunctionInfo):
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parsePropertyMethod):
* parser/Parser.h:
Add a duplicate parameter failure if there are duplicate parameters
in method syntax.
LayoutTests:
* js/parser-syntax-check-expected.txt:
* js/script-tests/parser-syntax-check.js:
Extend to cover method duplicate parameter cases.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@215723 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index b675495..602e623 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,43 @@
+2017-04-24 Joseph Pecoraro <pecoraro@apple.com>
+
+ test262: test262/test/language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js
+ https://bugs.webkit.org/show_bug.cgi?id=171190
+
+ Reviewed by Saam Barati.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::emitNewFunctionExpressionCommon):
+ (JSC::BytecodeGenerator::emitNewFunction):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::FunctionNode::emitBytecode):
+ (JSC::Scope::setSourceParseMode):
+ * parser/ParserModes.h:
+ (JSC::isFunctionParseMode):
+ (JSC::isMethodParseMode):
+ (JSC::isGeneratorOrAsyncFunctionWrapperParseMode):
+ (JSC::isGeneratorParseMode):
+ (JSC::isGeneratorWrapperParseMode):
+ * runtime/FunctionExecutable.h:
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::getOwnPropertySlot):
+ Add a new GeneratorWrapperMethodMode parse mode. The other function types
+ (async, arrow) already have a FunctionMode and a MethodMode. Give
+ generators one as well. This lets isMethodParseMode actually be accurate.
+
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseInner):
+ (JSC::Parser<LexerType>::isArrowFunctionParameters):
+ (JSC::Parser<LexerType>::parseFormalParameters):
+ (JSC::stringForFunctionMode):
+ (JSC::Parser<LexerType>::parseFunctionParameters):
+ (JSC::Parser<LexerType>::parseFunctionInfo):
+ (JSC::Parser<LexerType>::parseClass):
+ (JSC::Parser<LexerType>::parsePropertyMethod):
+ * parser/Parser.h:
+ Add a duplicate parameter failure if there are duplicate parameters
+ in method syntax.
+
2017-04-24 Andy VanWagoner <thetalecrafter@gmail.com>
Clean up ICU headers
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 048664d..f7724b5 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -534,7 +534,8 @@
m_newTargetRegister = addVar();
switch (parseMode) {
- case SourceParseMode::GeneratorWrapperFunctionMode: {
+ case SourceParseMode::GeneratorWrapperFunctionMode:
+ case SourceParseMode::GeneratorWrapperMethodMode: {
m_generatorRegister = addVar();
// FIXME: Emit to_this only when Generator uses it.
@@ -3229,6 +3230,7 @@
OpcodeID opcodeID = op_new_func_exp;
switch (function->parseMode()) {
case SourceParseMode::GeneratorWrapperFunctionMode:
+ case SourceParseMode::GeneratorWrapperMethodMode:
opcodeID = op_new_generator_func_exp;
break;
case SourceParseMode::AsyncFunctionMode:
@@ -3286,7 +3288,7 @@
RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionMetadataNode* function)
{
unsigned index = m_codeBlock->addFunctionDecl(makeFunction(function));
- if (function->parseMode() == SourceParseMode::GeneratorWrapperFunctionMode)
+ if (isGeneratorWrapperParseMode(function->parseMode()))
emitOpcode(op_new_generator_func);
else if (function->parseMode() == SourceParseMode::AsyncFunctionMode)
emitOpcode(op_new_async_func);
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index c33c9b8..9b3c943 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -3512,7 +3512,8 @@
generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
switch (generator.parseMode()) {
- case SourceParseMode::GeneratorWrapperFunctionMode: {
+ case SourceParseMode::GeneratorWrapperFunctionMode:
+ case SourceParseMode::GeneratorWrapperMethodMode: {
StatementNode* singleStatement = this->singleStatement();
ASSERT(singleStatement->isExprStatement());
ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp
index a8918b0..4d6c2e3 100644
--- a/Source/JavaScriptCore/parser/Parser.cpp
+++ b/Source/JavaScriptCore/parser/Parser.cpp
@@ -216,7 +216,7 @@
sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
else if (isModuleParseMode(parseMode))
sourceElements = parseModuleSourceElements(context, parseMode);
- else if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode)
+ else if (isGeneratorWrapperParseMode(parseMode))
sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
else
sourceElements = parseSourceElements(context, CheckForStrictMode);
@@ -239,7 +239,7 @@
for (auto& entry : capturedVariables)
varDeclarations.markVariableAsCaptured(entry);
- if (SourceParseModeSet(SourceParseMode::GeneratorWrapperFunctionMode).contains(parseMode) || isAsyncFunctionWrapperParseMode(parseMode)) {
+ if (isGeneratorWrapperParseMode(parseMode) || isAsyncFunctionWrapperParseMode(parseMode)) {
if (scope->usedVariablesContains(m_vm->propertyNames->arguments.impl()))
context.propagateArgumentsUse();
}
@@ -298,7 +298,8 @@
unsigned parametersCount = 0;
bool isArrowFunctionParameterList = true;
- isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
+ bool isMethod = false;
+ isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, isMethod, parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
propagateError();
popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
}
@@ -1850,7 +1851,7 @@
}
template <typename LexerType>
-template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, unsigned& parameterCount)
+template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, bool isMethod, unsigned& parameterCount)
{
#define failIfDuplicateIfViolation() \
if (duplicateParameter) {\
@@ -1858,6 +1859,7 @@
semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
semanticFailIfTrue(isRestParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with a rest parameter");\
semanticFailIfTrue(isArrowFunction, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in an arrow function");\
+ semanticFailIfTrue(isMethod, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in a method");\
}
bool hasDefaultParameterValues = false;
@@ -1951,6 +1953,7 @@
case SourceParseMode::GeneratorBodyMode:
return "generator";
case SourceParseMode::GeneratorWrapperFunctionMode:
+ case SourceParseMode::GeneratorWrapperMethodMode:
return "generator function";
case SourceParseMode::ArrowFunctionMode:
return "arrow function";
@@ -1990,7 +1993,8 @@
functionInfo.parameterCount = 0;
} else {
bool isArrowFunction = true;
- failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+ bool isMethod = false;
+ failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
}
consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
@@ -2034,7 +2038,8 @@
functionInfo.parameterCount = 0;
} else {
bool isArrowFunction = false;
- failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
+ bool isMethod = isMethodParseMode(mode);
+ failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
}
consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
}
@@ -2234,7 +2239,7 @@
semanticFailIfTrue(functionDefinitionType == FunctionDefinitionType::Declaration || isAsyncFunctionWrapperParseMode(mode), "Cannot declare function named 'await' ", isDisallowedAwaitFunctionNameReason);
else if (isAsyncFunctionWrapperParseMode(mode) && match(AWAIT) && functionDefinitionType == FunctionDefinitionType::Expression)
semanticFail("Cannot declare async function named 'await'");
- else if (mode == SourceParseMode::GeneratorWrapperFunctionMode && match(YIELD) && functionDefinitionType == FunctionDefinitionType::Expression)
+ else if (isGeneratorWrapperParseMode(mode) && match(YIELD) && functionDefinitionType == FunctionDefinitionType::Expression)
semanticFail("Cannot declare generator function named 'yield'");
next();
if (!nameIsInContainingScope)
@@ -2699,7 +2704,7 @@
semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare an async method named 'constructor'");
} else if (isGenerator) {
isConstructor = false;
- parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
+ parseMode = SourceParseMode::GeneratorWrapperMethodMode;
semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare a generator named 'prototype'");
semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare a generator named 'constructor'");
}
@@ -3823,7 +3828,7 @@
unsigned methodStart = tokenStart();
ParserFunctionInfo<TreeBuilder> methodInfo;
methodInfo.name = methodName;
- SourceParseMode parseMode = isGenerator ? SourceParseMode::GeneratorWrapperFunctionMode : isAsyncMethod ? SourceParseMode::AsyncMethodMode : SourceParseMode::MethodMode;
+ SourceParseMode parseMode = isGenerator ? SourceParseMode::GeneratorWrapperMethodMode : isAsyncMethod ? SourceParseMode::AsyncMethodMode : SourceParseMode::MethodMode;
failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
return context.createMethodDefinition(methodLocation, methodInfo);
}
diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h
index 94b3902..c35d5a1 100644
--- a/Source/JavaScriptCore/parser/Parser.h
+++ b/Source/JavaScriptCore/parser/Parser.h
@@ -276,6 +276,7 @@
break;
case SourceParseMode::GeneratorWrapperFunctionMode:
+ case SourceParseMode::GeneratorWrapperMethodMode:
setIsGeneratorFunction();
break;
@@ -1581,7 +1582,7 @@
template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, bool isGenerator, bool isAsyncMethod);
template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind, bool isClassProperty, bool isStaticMethod);
template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, SyntaxChecker&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, SuperBinding, FunctionBodyType, unsigned, SourceParseMode);
- template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, bool isArrowFunction, unsigned&);
+ template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, bool isArrowFunction, bool isMethod, unsigned&);
enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType, ExportType, bool& forLoopConstDoesNotHaveInitializer);
template <class TreeBuilder> TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&);
diff --git a/Source/JavaScriptCore/parser/ParserModes.h b/Source/JavaScriptCore/parser/ParserModes.h
index 5929846..9a96f5d 100644
--- a/Source/JavaScriptCore/parser/ParserModes.h
+++ b/Source/JavaScriptCore/parser/ParserModes.h
@@ -46,18 +46,19 @@
NormalFunctionMode = 0b0000000000000001,
GeneratorBodyMode = 0b0000000000000010,
GeneratorWrapperFunctionMode = 0b0000000000000100,
- GetterMode = 0b0000000000001000,
- SetterMode = 0b0000000000010000,
- MethodMode = 0b0000000000100000,
- ArrowFunctionMode = 0b0000000001000000,
- AsyncFunctionBodyMode = 0b0000000010000000,
- AsyncArrowFunctionBodyMode = 0b0000000100000000,
- AsyncFunctionMode = 0b0000001000000000,
- AsyncMethodMode = 0b0000010000000000,
- AsyncArrowFunctionMode = 0b0000100000000000,
- ProgramMode = 0b0001000000000000,
- ModuleAnalyzeMode = 0b0010000000000000,
- ModuleEvaluateMode = 0b0100000000000000,
+ GeneratorWrapperMethodMode = 0b0000000000001000,
+ GetterMode = 0b0000000000010000,
+ SetterMode = 0b0000000000100000,
+ MethodMode = 0b0000000001000000,
+ ArrowFunctionMode = 0b0000000010000000,
+ AsyncFunctionBodyMode = 0b0000000100000000,
+ AsyncArrowFunctionBodyMode = 0b0000001000000000,
+ AsyncFunctionMode = 0b0000010000000000,
+ AsyncMethodMode = 0b0000100000000000,
+ AsyncArrowFunctionMode = 0b0001000000000000,
+ ProgramMode = 0b0010000000000000,
+ ModuleAnalyzeMode = 0b0100000000000000,
+ ModuleEvaluateMode = 0b1000000000000000,
};
class SourceParseModeSet {
@@ -94,6 +95,7 @@
SourceParseMode::NormalFunctionMode,
SourceParseMode::GeneratorBodyMode,
SourceParseMode::GeneratorWrapperFunctionMode,
+ SourceParseMode::GeneratorWrapperMethodMode,
SourceParseMode::GetterMode,
SourceParseMode::SetterMode,
SourceParseMode::MethodMode,
@@ -140,8 +142,7 @@
ALWAYS_INLINE bool isMethodParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(
- // FIXME: GeneratorWrapperFunctionMode is not guaranteed to be a method.
- SourceParseMode::GeneratorWrapperFunctionMode,
+ SourceParseMode::GeneratorWrapperMethodMode,
SourceParseMode::GetterMode,
SourceParseMode::SetterMode,
SourceParseMode::MethodMode,
@@ -160,11 +161,27 @@
{
return SourceParseModeSet(
SourceParseMode::GeneratorWrapperFunctionMode,
+ SourceParseMode::GeneratorWrapperMethodMode,
SourceParseMode::AsyncFunctionMode,
SourceParseMode::AsyncArrowFunctionMode,
SourceParseMode::AsyncMethodMode).contains(parseMode);
}
+ALWAYS_INLINE bool isGeneratorParseMode(SourceParseMode parseMode)
+{
+ return SourceParseModeSet(
+ SourceParseMode::GeneratorBodyMode,
+ SourceParseMode::GeneratorWrapperFunctionMode,
+ SourceParseMode::GeneratorWrapperMethodMode).contains(parseMode);
+}
+
+ALWAYS_INLINE bool isGeneratorWrapperParseMode(SourceParseMode parseMode)
+{
+ return SourceParseModeSet(
+ SourceParseMode::GeneratorWrapperFunctionMode,
+ SourceParseMode::GeneratorWrapperMethodMode).contains(parseMode);
+}
+
ALWAYS_INLINE bool isArrowFunctionParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(
diff --git a/Source/JavaScriptCore/runtime/FunctionExecutable.h b/Source/JavaScriptCore/runtime/FunctionExecutable.h
index cee410d..7c1b088 100644
--- a/Source/JavaScriptCore/runtime/FunctionExecutable.h
+++ b/Source/JavaScriptCore/runtime/FunctionExecutable.h
@@ -123,7 +123,7 @@
bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; }
bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; }
- bool isGenerator() const { return SourceParseModeSet(SourceParseMode::GeneratorBodyMode, SourceParseMode::GeneratorWrapperFunctionMode).contains(parseMode()); }
+ bool isGenerator() const { return isGeneratorParseMode(parseMode()); }
bool isMethod() const { return parseMode() == SourceParseMode::MethodMode; }
bool hasCallerAndArgumentsProperties() const
{
@@ -136,7 +136,8 @@
return SourceParseModeSet(
SourceParseMode::NormalFunctionMode,
SourceParseMode::GeneratorBodyMode,
- SourceParseMode::GeneratorWrapperFunctionMode
+ SourceParseMode::GeneratorWrapperFunctionMode,
+ SourceParseMode::GeneratorWrapperMethodMode
).contains(parseMode()) || isClass();
}
DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); }
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp
index 51d4154..42f709c 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -358,7 +358,7 @@
PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName, attributes);
if (!isValidOffset(offset)) {
JSObject* prototype = nullptr;
- if (thisObject->jsExecutable()->parseMode() == SourceParseMode::GeneratorWrapperFunctionMode) {
+ if (isGeneratorWrapperParseMode(thisObject->jsExecutable()->parseMode())) {
// Unlike function instances, the object that is the value of the a GeneratorFunction's prototype
// property does not have a constructor property whose value is the GeneratorFunction instance.
// https://tc39.github.io/ecma262/#sec-generatorfunction-instances-prototype