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-144955-20150623130008.patch (text/plain), 88.62 KB, created by
GSkachkov
on 2015-06-23 03:00:53 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
GSkachkov
Created:
2015-06-23 03:00:53 PDT
Size:
88.62 KB
patch
obsolete
>Subversion Revision: 185867 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 7d96e889bb180f7bbabd482557e86127e95e38de..585dc1da2309d5c048547c61b9e2c912221f8f93 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,67 @@ >+2015-06-23 Aleksandr Skachkov <gskachkov@gmail.com> >+ >+ [ES6] Implement ES6 arrow function syntax. Parser of arrow function with execution as common function. >+ https://bugs.webkit.org/show_bug.cgi?id=144955 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Added support of ES6 arrow function. Changes were made according to following spec http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax. Patch does not include any arrow function specific behavior e.g. lexical bind this, arguments and etc. >+ This patch implements the simplest cases of arrow function declaration: >+ parameters () => 10 + 20 >+ parameter x => x + 20 >+ parameters (x, y) => x + y >+ function with block x => { return x*10; } >+ >+ Not implemented: >+ bind of the this, arguments, super and etc. >+ exception in case of trying to use 'new' with arrow function >+ >+ * parser/ASTBuilder.h: >+ (JSC::ASTBuilder::createFunctionExpr): >+ (JSC::ASTBuilder::createArrowFunctionExpr): >+ (JSC::ASTBuilder::createGetterOrSetterProperty): >+ (JSC::ASTBuilder::createFuncDeclStatement): >+ * parser/Lexer.cpp: >+ (JSC::Lexer<T>::setTokenPosition): >+ (JSC::Lexer<T>::lex): >+ * parser/Lexer.h: >+ (JSC::Lexer::lastTokenLocation): >+ (JSC::Lexer::setTerminator): >+ * parser/Parser.cpp: >+ (JSC::Parser<LexerType>::parseInner): >+ (JSC::Parser<LexerType>::parseSourceElements): >+ (JSC::Parser<LexerType>::parseArrowFunctionSingleExpressionBody): >+ (JSC::Parser<LexerType>::parseSwitchClauses): >+ (JSC::Parser<LexerType>::parseSwitchDefaultClause): >+ (JSC::Parser<LexerType>::parseBlockStatement): >+ (JSC::Parser<LexerType>::parseStatement): >+ (JSC::Parser<LexerType>::parseFunctionBody): >+ (JSC::stringForFunctionMode): >+ (JSC::Parser<LexerType>::parseFunctionParameters): >+ (JSC::Parser<LexerType>::parseFunctionInfo): >+ (JSC::Parser<LexerType>::parseFunctionDeclaration): >+ (JSC::Parser<LexerType>::parseClass): >+ (JSC::Parser<LexerType>::parseAssignmentExpression): >+ (JSC::Parser<LexerType>::parsePropertyMethod): >+ (JSC::Parser<LexerType>::parseGetterSetter): >+ (JSC::Parser<LexerType>::parsePrimaryExpression): >+ (JSC::Parser<LexerType>::parseArrowFunctionWrapper): >+ * parser/Parser.h: >+ (JSC::Parser::locationBeforeLastToken): >+ (JSC::Parser::isEndOfArrowFunction): >+ (JSC::Parser::isArrowFunctionParamters): >+ (JSC::Parser::setEndOfStatement): >+ * parser/ParserFunctionInfo.h: >+ * parser/ParserTokens.h: >+ * parser/SourceCode.h: >+ (JSC::SourceCode::subArrowExpression): >+ * parser/SourceProviderCacheItem.h: >+ (JSC::SourceProviderCacheItem::endFunctionToken): >+ (JSC::SourceProviderCacheItem::SourceProviderCacheItem): >+ * parser/SyntaxChecker.h: >+ (JSC::SyntaxChecker::createArrowFunctionExpr): >+ (JSC::SyntaxChecker::setFunctionNameStart): >+ > 2015-06-22 Yusuke Suzuki <utatane.tea@gmail.com> > > [ES6] Allow trailing comma in ArrayBindingPattern and ObjectBindingPattern >diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h >index c3be60dabe86e4972df241c8348df5049b0f8d2d..2acc54934ab7fef399e3ce3d5248bb00270231f7 100644 >--- a/Source/JavaScriptCore/parser/ASTBuilder.h >+++ b/Source/JavaScriptCore/parser/ASTBuilder.h >@@ -347,7 +347,7 @@ public: > ExpressionNode* createFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& info) > { > FuncExprNode* result = new (m_parserArena) FuncExprNode(location, *info.name, info.body, >- m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters); >+ m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters); > info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset); > return result; > } >@@ -364,13 +364,26 @@ public: > inStrictContext, constructorKind); > } > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ ExpressionNode* createArrowFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& info) >+ { >+ SourceCode source = info.functionBodyType == ArrowFunctionBodyExpression >+ ? m_sourceCode->subArrowExpression(info.arrowFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn, info.isEndByTerminator) >+ : m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn); >+ >+ FuncExprNode* result = new (m_parserArena) FuncExprNode(location, *info.name, info.body, source, info.parameters); >+ info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset); >+ return result; >+ } >+#endif >+ > NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool, > const Identifier* name, const ParserFunctionInfo<ASTBuilder>& info, SuperBinding superBinding) > { > ASSERT(name); > info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset); > info.body->setInferredName(*name); >- SourceCode source = m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn); >+ SourceCode source = m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn); > FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, info.body, source, info.parameters); > return new (m_parserArena) PropertyNode(*name, funcExpr, type, PropertyNode::Unknown, superBinding); > } >@@ -380,7 +393,7 @@ public: > { > info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset); > const Identifier& ident = parserArena.identifierArena().makeNumericIdentifier(vm, name); >- SourceCode source = m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn); >+ SourceCode source = m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn); > FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, vm->propertyNames->nullIdentifier, info.body, source, info.parameters); > return new (m_parserArena) PropertyNode(ident, funcExpr, type, PropertyNode::Unknown, superBinding); > } >@@ -417,7 +430,7 @@ public: > StatementNode* createFuncDeclStatement(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& info) > { > FuncDeclNode* decl = new (m_parserArena) FuncDeclNode(location, *info.name, info.body, >- m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters); >+ m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters); > if (*info.name == m_vm->propertyNames->arguments) > usesArguments(); > m_scope.m_funcDeclarations.append(decl->body()); >diff --git a/Source/JavaScriptCore/parser/Lexer.cpp b/Source/JavaScriptCore/parser/Lexer.cpp >index 5c0c3f9b12d1d11c5b692c4593571ec4682dc11f..53aa9b05f09c00da3f1a69b02dc06666abdbef1a 100644 >--- a/Source/JavaScriptCore/parser/Lexer.cpp >+++ b/Source/JavaScriptCore/parser/Lexer.cpp >@@ -1715,11 +1715,25 @@ bool Lexer<T>::nextTokenIsColon() > return code < m_codeEnd && *code == ':'; > } > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+template <typename T> >+void Lexer<T>::setTokenPosition(JSToken* tokenRecord) >+{ >+ JSTokenData* tokenData = &tokenRecord->m_data; >+ tokenData->line = lineNumber(); >+ tokenData->offset = currentOffset(); >+ tokenData->lineStartOffset = currentLineStartOffset(); >+ ASSERT(tokenData->offset >= tokenData->lineStartOffset); >+} >+#endif >+ > template <typename T> > JSTokenType Lexer<T>::lex(JSToken* tokenRecord, unsigned lexerFlags, bool strictMode) > { > JSTokenData* tokenData = &tokenRecord->m_data; > JSTokenLocation* tokenLocation = &tokenRecord->m_location; >+ m_lastTockenLocation = JSTokenLocation(tokenRecord->m_location); >+ > ASSERT(!m_error); > ASSERT(m_buffer8.isEmpty()); > ASSERT(m_buffer16.isEmpty()); >@@ -1778,7 +1792,19 @@ start: > } > token = GT; > break; >- case CharacterEqual: >+ case CharacterEqual: { >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if (peek(1) == '>') { >+ token = ARROWFUNCTION; >+ tokenData->line = lineNumber(); >+ tokenData->offset = currentOffset(); >+ tokenData->lineStartOffset = currentLineStartOffset(); >+ ASSERT(tokenData->offset >= tokenData->lineStartOffset); >+ shift(); >+ shift(); >+ break; >+ } >+#endif > shift(); > if (m_current == '=') { > shift(); >@@ -1792,6 +1818,7 @@ start: > } > token = EQUAL; > break; >+ } > case CharacterLess: > shift(); > if (m_current == '!' && peek(1) == '-' && peek(2) == '-') { >diff --git a/Source/JavaScriptCore/parser/Lexer.h b/Source/JavaScriptCore/parser/Lexer.h >index cab7d52960d44b85f0813f72524b51542bfebe08..b142c484a4057d472736a2e9932b8b86d79d1c21 100644 >--- a/Source/JavaScriptCore/parser/Lexer.h >+++ b/Source/JavaScriptCore/parser/Lexer.h >@@ -87,6 +87,9 @@ public: > void setIsReparsing() { m_isReparsing = true; } > bool isReparsing() const { return m_isReparsing; } > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ void setTokenPosition(JSToken* tokenRecord); >+#endif > JSTokenType lex(JSToken*, unsigned, bool strictMode); > bool nextTokenIsColon(); > int lineNumber() const { return m_lineNumber; } >@@ -97,6 +100,7 @@ public: > return JSTextPosition(m_lineNumber, currentOffset(), currentLineStartOffset()); > } > JSTextPosition positionBeforeLastNewline() const { return m_positionBeforeLastNewline; } >+ JSTokenLocation lastTokenLocation() const { return m_lastTockenLocation; } > void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; } > int lastLineNumber() const { return m_lastLineNumber; } > bool prevTerminator() const { return m_terminator; } >@@ -131,6 +135,10 @@ public: > { > m_lineNumber = line; > } >+ void setTerminator(bool terminator) >+ { >+ m_terminator = terminator; >+ } > > SourceProvider* sourceProvider() const { return m_source->provider(); } > >@@ -215,6 +223,7 @@ private: > const T* m_codeStartPlusOffset; > const T* m_lineStart; > JSTextPosition m_positionBeforeLastNewline; >+ JSTokenLocation m_lastTockenLocation; > bool m_isReparsing; > bool m_atLineStart; > bool m_error; >diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp >index dab6b1a14d73d71fb7a8d60553d8016e48f039d9..d0db950cbbc33c2bbac205f002045dd1b442e7db 100644 >--- a/Source/JavaScriptCore/parser/Parser.cpp >+++ b/Source/JavaScriptCore/parser/Parser.cpp >@@ -264,7 +264,7 @@ String Parser<LexerType>::parseInner() > if (m_lexer->isReparsing()) > m_statementDepth--; > ScopeRef scope = currentScope(); >- SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode); >+ SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode, StandardFunctionParseType); > if (!sourceElements || !consume(EOFTOK)) { > if (hasError()) > parseError = m_errorMessage; >@@ -343,7 +343,7 @@ bool Parser<LexerType>::allowAutomaticSemicolon() > } > > template <typename LexerType> >-template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode) >+template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode, FunctionParseType functionParseType) > { > const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length > TreeSourceElements sourceElements = context.createSourceElements(); >@@ -352,7 +352,7 @@ template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceEl > unsigned directiveLiteralLength = 0; > auto savePoint = createSavePoint(); > bool hasSetStrict = false; >- while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) { >+ while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength, functionParseType)) { > if (mode == CheckForStrictMode && !seenNonDirective) { > if (directive) { > // "use strict" must be the exact literal without escape sequences or line continuation. >@@ -583,6 +583,41 @@ template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::create > return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition); > } > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+template <typename LexerType> >+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseArrowFunctionSingleExpressionBody(TreeBuilder& context, FunctionParseType parseType) >+{ >+ ASSERT(match(ARROWFUNCTION)); >+ >+ if (!m_lexer->isReparsing() && parseType != ArrowFunctionParseType) >+ failDueToUnexpectedToken(); >+ >+ JSTokenLocation location(tokenLocation()); >+ JSTextPosition start = tokenStartPosition(); >+ JSTextPosition end = tokenEndPosition(); >+ >+ next(); >+ >+ failIfStackOverflow(); >+ TreeExpression expr = parseAssignmentExpression(context); >+ failIfFalse(expr, "Cannot parse the arrow function expression"); >+ >+ context.setEndOffset(expr, m_lastTokenEndPosition.offset); >+ >+ failIfFalse(isEndOfArrowFunction(), "Expected a ';', ']', '}', ')', ',', line terminator or EOF following a arrow function statement"); >+ >+ end = tokenEndPosition(); >+ >+ if (!m_lexer->prevTerminator()) >+ setEndOfStatement(); >+ >+ if (parseType == StandardFunctionParseType) >+ next(); >+ >+ return context.createReturnStatement(location, expr, start, end); >+} >+#endif >+ > template <typename LexerType> > template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::tryParseDeconstructionPatternExpression(TreeBuilder& context) > { >@@ -1048,7 +1083,7 @@ template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClause > TreeExpression condition = parseExpression(context); > failIfFalse(condition, "Cannot parse switch clause"); > consumeOrFail(COLON, "Expected a ':' after switch clause expression"); >- TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode); >+ TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType); > failIfFalse(statements, "Cannot parse the body of a switch clause"); > TreeClause clause = context.createClause(condition, statements); > context.setStartOffset(clause, startOffset); >@@ -1061,7 +1096,7 @@ template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClause > TreeExpression condition = parseExpression(context); > failIfFalse(condition, "Cannot parse switch case expression"); > consumeOrFail(COLON, "Expected a ':' after switch clause expression"); >- TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode); >+ TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType); > failIfFalse(statements, "Cannot parse the body of a switch clause"); > clause = context.createClause(condition, statements); > context.setStartOffset(clause, startOffset); >@@ -1078,7 +1113,7 @@ template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultCla > unsigned startOffset = tokenStart(); > next(); > consumeOrFail(COLON, "Expected a ':' after switch default clause"); >- TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode); >+ TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType); > failIfFalse(statements, "Cannot parse the body of a switch default clause"); > TreeClause result = context.createClause(0, statements); > context.setStartOffset(result, startOffset); >@@ -1163,7 +1198,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatemen > context.setEndOffset(result, endOffset); > return result; > } >- TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode); >+ TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType); > failIfFalse(subtree, "Cannot parse the body of the block statement"); > matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement"); > int endOffset = m_token.m_data.offset; >@@ -1175,7 +1210,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatemen > } > > template <typename LexerType> >-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength) >+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength, FunctionParseType parseType) > { > DepthManager statementDepth(&m_statementDepth); > m_statementDepth++; >@@ -1184,6 +1219,11 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(Tre > failIfStackOverflow(); > TreeStatement result = 0; > bool shouldSetEndOffset = true; >+ >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if (parseType == ArrowFunctionParseType && isEndOfArrowFunction()) >+ return result; >+#endif > switch (m_token.m_type) { > case OPENBRACE: > result = parseBlockStatement(context); >@@ -1229,6 +1269,11 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(Tre > case BREAK: > result = parseBreakStatement(context); > break; >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ case ARROWFUNCTION: >+ result = parseArrowFunctionSingleExpressionBody(context, parseType); >+ break; >+#endif > case RETURN: > result = parseReturnStatement(context); > break; >@@ -1293,20 +1338,27 @@ template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFor > template <typename LexerType> > template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody( > TreeBuilder& context, int functionKeywordStart, int functionNameStart, >- int parametersStart, ConstructorKind constructorKind) >+ int parametersStart, ConstructorKind constructorKind, FunctionParseType parseType) > { > JSTokenLocation startLocation(tokenLocation()); > unsigned startColumn = tokenColumn(); >- next(); > >- if (match(CLOSEBRACE)) { >- unsigned endColumn = tokenColumn(); >- return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind); >+ if (parseType == StandardFunctionParseType) { >+ next(); >+ if (match(CLOSEBRACE)) { >+ unsigned endColumn = tokenColumn(); >+ return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind); >+ } > } >+ > DepthManager statementDepth(&m_statementDepth); > m_statementDepth = 0; > typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get()); >- failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode), "Cannot parse body of this function"); >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, parseType), parseType == StandardFunctionParseType ? "Cannot parse body of this function" : "Cannot parse body of this arrow function"); >+#else >+ failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, StandardFunctionParseType), "Cannot parse body of this function"); >+#endif > unsigned endColumn = tokenColumn(); > return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind); > } >@@ -1322,27 +1374,46 @@ static const char* stringForFunctionMode(FunctionParseMode mode) > return "function"; > case MethodMode: > return "method"; >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ case ArrowFunctionMode: >+ return "arrow function"; >+#endif > } > RELEASE_ASSERT_NOT_REACHED(); > return nullptr; > } > >-template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, AutoPopScopeRef& functionScope, ParserFunctionInfo<TreeBuilder>& info) >+template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionParseMode mode, ParserFunctionInfo<TreeBuilder>& info) > { >- if (match(IDENT)) { >- info.name = m_token.m_data.ident; >- m_lastFunctionName = info.name; >- next(); >- if (!nameIsInContainingScope) >- failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode"); >- } else if (requirements == FunctionNeedsName) { >- if (match(OPENPAREN) && mode == FunctionMode) >- semanticFail("Function statements must have a name"); >- semanticFailureDueToKeyword(stringForFunctionMode(mode), " name"); >- failDueToUnexpectedToken(); >- return false; >- } > int parametersStart = m_token.m_location.startOffset; >+ >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if (mode == ArrowFunctionMode) { >+ if (!match(IDENT) && !match(OPENPAREN)) { >+ semanticFailureDueToKeyword(stringForFunctionMode(mode), " name"); >+ failWithMessage("Expected an arrow function input parameter"); >+ } else { >+ if (match(OPENPAREN)) { >+ next(); >+ >+ if (!match(CLOSEPAREN)) { >+ info.parameters = parseFormalParameters(context); >+ failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode)); >+ } >+ >+ consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration"); >+ } else { >+ auto parameter = parseDeconstructionPattern(context, DeconstructToParameters); >+ failIfFalse(parameter, "Cannot parse parameter pattern"); >+ info.parameters = context.createFormalParameterList(parameter); >+ failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode)); >+ } >+ } >+ >+ return parametersStart; >+ } >+#endif >+ > if (!consume(OPENPAREN)) { > semanticFailureDueToKeyword(stringForFunctionMode(mode), " name"); > failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list"); >@@ -1367,43 +1438,78 @@ template <typename LexerType> template <class TreeBuilder> int Parser<LexerType> > > return parametersStart; > } >- >+ > template <typename LexerType> >-template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& info) >+template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& info, FunctionParseType parseType) > { > AutoPopScopeRef functionScope(this, pushScope()); > functionScope->setIsFunction(); > int functionNameStart = m_token.m_location.startOffset; > const Identifier* lastFunctionName = m_lastFunctionName; > m_lastFunctionName = nullptr; >+ int parametersStart; > >- int parametersStart = parseFunctionParameters(context, requirements, mode, nameIsInContainingScope, functionScope, info); >- propagateError(); >- >- matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body"); >- >- // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed. >- // Set ConstructorKind to None for non-constructor methods of classes. >- if (m_defaultConstructorKind != ConstructorKind::None) { >- constructorKind = m_defaultConstructorKind; >- expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded; >+ switch (parseType) { >+ case StandardFunctionParseType: { >+ if (match(IDENT)) { >+ info.name = m_token.m_data.ident; >+ m_lastFunctionName = info.name; >+ next(); >+ if (!nameIsInContainingScope) >+ failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode"); >+ } else if (requirements == FunctionNeedsName) { >+ if (match(OPENPAREN) && mode == FunctionMode) >+ semanticFail("Function statements must have a name"); >+ semanticFailureDueToKeyword(stringForFunctionMode(mode), " name"); >+ failDueToUnexpectedToken(); >+ return false; >+ } >+ >+ parametersStart = parseFunctionParameters(context, mode, info); >+ propagateError(); >+ >+ matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body"); >+ >+ // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed. >+ // Set ConstructorKind to None for non-constructor methods of classes. >+ >+ if (m_defaultConstructorKind != ConstructorKind::None) { >+ constructorKind = m_defaultConstructorKind; >+ expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded; >+ } >+ >+ break; >+ } >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ case ArrowFunctionParseType: { >+ parametersStart = parseFunctionParameters(context, ArrowFunctionMode, info); >+ propagateError(); >+ >+ matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration"); >+ ASSERT(constructorKind == ConstructorKind::None); >+ >+ info.arrowFunctionOffset = m_token.m_data.offset; >+ break; >+ } >+#endif > } >+ > bool isClassConstructor = constructorKind != ConstructorKind::None; > >- info.openBraceOffset = m_token.m_data.offset; >+ info.startFunctionOffset = m_token.m_data.offset; > info.bodyStartLine = tokenLine(); > info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset; > JSTokenLocation startLocation(tokenLocation()); > > // If we know about this function already, we can use the cached info and skip the parser to the end of the function. >- if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.openBraceOffset) : 0) { >+ if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.startFunctionOffset) : 0) { > // If we're in a strict context, the cached function info must say it was strict too. > ASSERT(!strictMode() || cachedInfo->strictMode); > JSTokenLocation endLocation; > >- endLocation.line = cachedInfo->closeBraceLine; >- endLocation.startOffset = cachedInfo->closeBraceOffset; >- endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset; >+ endLocation.line = cachedInfo->endFunctionLine; >+ endLocation.startOffset = cachedInfo->endFunctionStartOffset; >+ endLocation.lineStartOffset = cachedInfo->endFunctionLineStartOffset; > > bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine); > ASSERT(endLocation.startOffset >= endLocation.lineStartOffset); >@@ -1420,24 +1526,67 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild > functionScope->restoreFromSourceProviderCache(cachedInfo); > failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error"); > >- info.closeBraceOffset = cachedInfo->closeBraceOffset; >- >- m_token = cachedInfo->closeBraceToken(); >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if (parseType == ArrowFunctionParseType) >+ info.functionBodyType = cachedInfo->isBodyArrowExpression ? ArrowFunctionBodyExpression : ArrowFunctionBodyBlock; >+ else >+ info.functionBodyType = StandardFunctionBodyBlock; >+#endif >+ m_token = cachedInfo->endFunctionToken(); >+ > if (endColumnIsOnStartLine) > m_token.m_location.lineStartOffset = currentLineStartOffset; > > m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset); > m_lexer->setLineNumber(m_token.m_location.line); >- >+ info.endFunctionOffset = m_token.m_location.startOffset; >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ info.isEndByTerminator = cachedInfo->isPrevTerminator; >+ if (parseType == ArrowFunctionParseType && cachedInfo->isBodyArrowExpression && cachedInfo->isPrevTerminator) { >+ info.endFunctionOffset = m_token.m_location.endOffset; >+ next(); >+ } >+#endif >+ > context.setEndOffset(info.body, m_lexer->currentOffset()); > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if (parseType != ArrowFunctionParseType || info.functionBodyType == ArrowFunctionBodyBlock) >+ next(); >+#else > next(); >+#endif > info.bodyEndLine = m_lastTokenEndPosition.line; > return true; > } >+ > m_lastFunctionName = lastFunctionName; > ParserState oldState = saveState(); >- info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind); >+ >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if (parseType == ArrowFunctionParseType) { >+ SavePoint savePoint = createSavePoint(); >+ next(); >+ // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function >+ // and we need use common approach to parse function body >+ info.functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression; >+ >+ if (info.functionBodyType == ArrowFunctionBodyBlock) { >+ info.startFunctionOffset = m_token.m_data.offset; >+ info.bodyStartLine = tokenLine(); >+ info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset; >+ >+ info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType); >+ } else { >+ restoreSavePoint(savePoint); >+ info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, ArrowFunctionParseType); >+ } >+ } else >+ info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType); >+#else >+ info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType); >+#endif >+ > restoreState(oldState); > failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode)); > context.setEndOffset(info.body, m_lexer->currentOffset()); >@@ -1453,33 +1602,61 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild > if (functionScope->needsSuperBinding()) > semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class"); > >- info.closeBraceOffset = m_token.m_data.offset; >- unsigned closeBraceLine = m_token.m_data.line; >- unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset; >+ JSTokenLocation location = JSTokenLocation(m_token.m_location); >+ info.endFunctionOffset = m_token.m_data.offset; >+ >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if (info.functionBodyType == ArrowFunctionBodyExpression && m_lexer->prevTerminator()) { >+ location = locationBeforeLastToken(); >+ info.endFunctionOffset = location.endOffset + 1; >+ info.isEndByTerminator = true; >+ } >+#endif >+ >+ unsigned endFunctionOffset = location.startOffset; >+ unsigned endFunctionLine = location.line; >+ unsigned endFunctionLineStartOffset = location.lineStartOffset; >+ unsigned endFunctionEndOffset = location.endOffset; > > // Cache the tokenizer state and the function scope the first time the function is parsed. > // Any future reparsing can then skip the function. > static const int minimumFunctionLengthToCache = 16; > std::unique_ptr<SourceProviderCacheItem> newInfo; >- int functionLength = info.closeBraceOffset - info.openBraceOffset; >+ int functionLength = info.endFunctionOffset - info.startFunctionOffset; > if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) { > SourceProviderCacheItemCreationParameters parameters; > parameters.functionNameStart = functionNameStart; >- parameters.closeBraceLine = closeBraceLine; >- parameters.closeBraceOffset = info.closeBraceOffset; >- parameters.closeBraceLineStartOffset = closeBraceLineStartOffset; >+ parameters.endFunctionLine = endFunctionLine; >+ parameters.endFunctionStartOffset = endFunctionOffset; >+ parameters.endFunctionEndOffset = endFunctionEndOffset; >+ parameters.endFunctionLineStartOffset = endFunctionLineStartOffset; >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if (parseType == ArrowFunctionParseType) { >+ parameters.isBodyArrowExpression = info.functionBodyType == ArrowFunctionBodyExpression; >+ parameters.tokenType = m_token.m_type; >+ parameters.isPrevTerminator = m_lexer->prevTerminator(); >+ } >+#endif > functionScope->fillParametersForSourceProviderCache(parameters); > newInfo = SourceProviderCacheItem::create(parameters); >- > } > > failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error"); >+ >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if ((parseType == ArrowFunctionParseType && info.functionBodyType == ArrowFunctionBodyBlock) || parseType != ArrowFunctionParseType) { >+ matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body"); >+ next(); >+ } else >+ failIfFalse(isEndOfArrowFunction(), "Expected the closing ';' ',' ']' ')' '}', line terminator or EOF after arrow function"); >+#else > matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body"); >+ next(); >+#endif > > if (newInfo) >- m_functionCache->add(info.openBraceOffset, WTF::move(newInfo)); >+ m_functionCache->add(info.startFunctionOffset, WTF::move(newInfo)); > >- next(); > info.bodyEndLine = m_lastTokenEndPosition.line; > return true; > } >@@ -1493,7 +1670,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla > next(); > ParserFunctionInfo<TreeBuilder> info; > failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, >- functionKeywordStart, info)), "Cannot parse this function"); >+ functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse this function"); > failIfFalse(info.name, "Function statements must have a name"); > failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode"); > return context.createFuncDeclStatement(location, info); >@@ -1612,8 +1789,7 @@ template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(T > } else { > ParserFunctionInfo<TreeBuilder> methodInfo; > bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor; >- failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false, >- isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo)), "Cannot parse this method"); >+ failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method"); > failIfFalse(ident && declareVariable(ident), "Cannot declare a method named '", methodInfo.name->impl(), "'"); > methodInfo.name = isConstructor ? className : ident; > >@@ -1854,6 +2030,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(T > return head; > } > >+ > template <typename LexerType> > template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context) > { >@@ -1872,6 +2049,12 @@ template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmen > } > restoreSavePoint(savePoint); > } >+ >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ if (isArrowFunctionParamters()) >+ return parseArrowFunctionWrapper(context); >+#endif >+ > TreeExpression lhs = parseConditionalExpression(context); > failIfFalse(lhs, "Cannot parse expression"); > if (initialNonLHSCount != m_nonLHSCount) { >@@ -2112,8 +2295,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMeth > JSTokenLocation methodLocation(tokenLocation()); > unsigned methodStart = tokenStart(); > ParserFunctionInfo<TreeBuilder> methodInfo; >- failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded, >- methodStart, methodInfo)), "Cannot parse this method"); >+ failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method"); > methodInfo.name = methodName; > return context.createFunctionExpr(methodLocation, methodInfo); > } >@@ -2140,11 +2322,11 @@ template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(T > if (type & PropertyNode::Getter) { > failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition"); > failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, constructorKind, superBinding, >- getterOrSetterStartOffset, info)), "Cannot parse getter definition"); >+ getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse getter definition"); > } else { > failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition"); > failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, constructorKind, superBinding, >- getterOrSetterStartOffset, info)), "Cannot parse setter definition"); >+ getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse setter definition"); > } > if (stringPropertyName) > return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, superBinding); >@@ -2411,8 +2593,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre > next(); > ParserFunctionInfo<TreeBuilder> info; > info.name = &m_vm->propertyNames->nullIdentifier; >- failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, >- functionKeywordStart, info)), "Cannot parse function expression"); >+ failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse function expression"); > return context.createFunctionExpr(location, info); > } > #if ENABLE(ES6_CLASS_SYNTAX) >@@ -2444,7 +2625,17 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre > JSTextPosition start = tokenStartPosition(); > const Identifier* ident = m_token.m_data.ident; > JSTokenLocation location(tokenLocation()); >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ SavePoint saveArrowFunctionPoint = createSavePoint(); >+ next(); >+ >+ if (match(ARROWFUNCTION)) { >+ restoreSavePoint(saveArrowFunctionPoint); >+ return parseArrowFunctionWrapper(context); >+ } >+#else > next(); >+#endif > currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident); > m_lastIdentifier = ident; > return context.createResolve(location, ident, start); >@@ -2652,6 +2843,23 @@ endMemberExpression: > return base; > } > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+template <typename LexerType> >+template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrowFunctionWrapper(TreeBuilder& context) >+{ >+ JSTokenLocation location; >+ >+ failIfFalse(match(IDENT) || match(OPENPAREN), "Expected an arrow function input parameter"); >+ unsigned functionKeywordStart = tokenStart(); >+ location = tokenLocation(); >+ ParserFunctionInfo<TreeBuilder> info; >+ info.name = &m_vm->propertyNames->nullIdentifier; >+ failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, ArrowFunctionParseType)), "Cannot parse arrow function expression"); >+ >+ return context.createArrowFunctionExpr(location, info); >+} >+#endif >+ > static const char* operatorString(bool prefix, unsigned tok) > { > switch (tok) { >diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h >index 21c6e1f27d0372f0df3babad74454d38f84d9ca1..d312b24a0ceb994ee007ff419b6cdb55a26d0d24 100644 >--- a/Source/JavaScriptCore/parser/Parser.h >+++ b/Source/JavaScriptCore/parser/Parser.h >@@ -80,12 +80,20 @@ class SourceCode; > COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens); > > enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode }; >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+enum FunctionParseType { StandardFunctionParseType, ArrowFunctionParseType }; >+#else >+enum FunctionParseType { StandardFunctionParseType}; >+#endif > enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName }; > enum FunctionParseMode { > FunctionMode, > GetterMode, > SetterMode, > MethodMode, >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ ArrowFunctionMode >+#endif > }; > enum DeconstructionKind { > DeconstructToVariables, >@@ -430,6 +438,7 @@ public: > std::unique_ptr<ParsedNode> parse(ParserError&); > > JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); } >+ JSTokenLocation locationBeforeLastToken() const { return m_lexer->lastTokenLocation(); } > Vector<RefPtr<UniquedStringImpl>>&& closedVariables() { return WTF::move(m_closedVariables); } > > private: >@@ -612,6 +621,47 @@ private: > return m_token.m_type == IDENT && *m_token.m_data.ident == m_vm->propertyNames->of; > } > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ ALWAYS_INLINE bool isEndOfArrowFunction() >+ { >+ return match(SEMICOLON) || match(COMMA) || match(CLOSEPAREN) || match(CLOSEBRACE) || match(CLOSEBRACKET) || match(EOFTOK) || m_lexer->prevTerminator(); >+ } >+ >+ ALWAYS_INLINE bool isArrowFunctionParamters() >+ { >+ bool isArrowFunction = false; >+ >+ if (match(EOFTOK)) >+ return isArrowFunction; >+ >+ SavePoint saveArrowFunctionPoint = createSavePoint(); >+ >+ if (consume(OPENPAREN)) { >+ bool isArrowFunctionParamters = true; >+ >+ while (consume(IDENT)) { >+ if (consume(COMMA)) { >+ if (!match(IDENT)) { >+ isArrowFunctionParamters = false; >+ break; >+ } >+ } else >+ break; >+ } >+ >+ if (isArrowFunctionParamters) { >+ if (consume(CLOSEPAREN) && match(ARROWFUNCTION)) >+ isArrowFunction = true; >+ } >+ } else if (consume(IDENT) && match(ARROWFUNCTION)) >+ isArrowFunction = true; >+ >+ restoreSavePoint(saveArrowFunctionPoint); >+ >+ return isArrowFunction; >+ } >+#endif >+ > ALWAYS_INLINE unsigned tokenStart() > { > return m_token.m_location.startOffset; >@@ -715,9 +765,9 @@ private: > } > return result; > } >- >- template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode); >- template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0); >+ >+ template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode, FunctionParseType); >+ template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0, FunctionParseType = StandardFunctionParseType); > #if ENABLE(ES6_CLASS_SYNTAX) > template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&); > #endif >@@ -756,24 +806,30 @@ private: > template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict); > template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName); > template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind = ConstructorKind::None, SuperBinding = SuperBinding::NotNeeded); >- template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind); >+ template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, FunctionParseType); > template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&); > enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext }; > template <class TreeBuilder> TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext); > template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&); > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ template <class TreeBuilder> TreeStatement parseArrowFunctionSingleExpressionBody(TreeBuilder&, FunctionParseType); >+ template <class TreeBuilder> TreeExpression parseArrowFunctionWrapper(TreeBuilder&); >+#endif >+ > template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern createBindingPattern(TreeBuilder&, DeconstructionKind, const Identifier&, int depth, JSToken); > template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&, DeconstructionKind, int depth = 0); > template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&); > template <class TreeBuilder> NEVER_INLINE TreeExpression parseDefaultValueForDeconstructionPattern(TreeBuilder&); > >- template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&); >+ template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionParseType); > >- template <class TreeBuilder> NEVER_INLINE int parseFunctionParameters(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool, AutoPopScopeRef&, ParserFunctionInfo<TreeBuilder>&); >+ template <class TreeBuilder> NEVER_INLINE int parseFunctionParameters(TreeBuilder&, FunctionParseMode, ParserFunctionInfo<TreeBuilder>&); > > #if ENABLE(ES6_CLASS_SYNTAX) > template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionRequirements, ParserClassInfo<TreeBuilder>&); > #endif >+ > #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX) > template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateString parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode, bool& elementIsTail); > template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateLiteral parseTemplateLiteral(TreeBuilder&, typename LexerType::RawStringsBuildMode); >@@ -793,6 +849,14 @@ private: > return allowAutomaticSemicolon(); > } > >+ >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ void setEndOfStatement() >+ { >+ m_lexer->setTokenPosition(&m_token); >+ } >+#endif >+ > bool canRecurse() > { > return m_vm->isSafeToRecurse(); >diff --git a/Source/JavaScriptCore/parser/ParserFunctionInfo.h b/Source/JavaScriptCore/parser/ParserFunctionInfo.h >index 6b736282e2d2a81bc63dc2f3c0e5ae8c858cd1f8..541c25e46ba86d2e23a9c1836f708217a087739f 100644 >--- a/Source/JavaScriptCore/parser/ParserFunctionInfo.h >+++ b/Source/JavaScriptCore/parser/ParserFunctionInfo.h >@@ -28,16 +28,26 @@ > > namespace JSC { > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+enum FunctionBodyType { ArrowFunctionBodyExpression, ArrowFunctionBodyBlock, StandardFunctionBodyBlock }; >+#endif >+ > template <class TreeBuilder> > struct ParserFunctionInfo { > const Identifier* name = 0; > typename TreeBuilder::FormalParameterList parameters = 0; > typename TreeBuilder::FunctionBody body = 0; >- unsigned openBraceOffset = 0; >- unsigned closeBraceOffset = 0; >+ unsigned startFunctionOffset = 0; >+ unsigned endFunctionOffset = 0; > int bodyStartLine = 0; > int bodyEndLine = 0; > unsigned bodyStartColumn = 0; >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ unsigned arrowFunctionOffset = 0; >+ bool isArrowFunction { false }; >+ bool isEndByTerminator { false }; >+ FunctionBodyType functionBodyType { StandardFunctionBodyBlock }; >+#endif > }; > > #if ENABLE(ES6_CLASS_SYNTAX) >diff --git a/Source/JavaScriptCore/parser/ParserTokens.h b/Source/JavaScriptCore/parser/ParserTokens.h >index 026e4f80f437d8bfe4a619c30d11dc9fc61e2645..e9154caf053c5381b5f09816dba0558a5434bf37 100644 >--- a/Source/JavaScriptCore/parser/ParserTokens.h >+++ b/Source/JavaScriptCore/parser/ParserTokens.h >@@ -75,6 +75,9 @@ enum JSTokenType { > FINALLY, > DEBUGGER, > ELSE, >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ ARROWFUNCTION, >+#endif > #if ENABLE(ES6_CLASS_SYNTAX) > CLASSTOKEN, > EXTENDS, >diff --git a/Source/JavaScriptCore/parser/SourceCode.h b/Source/JavaScriptCore/parser/SourceCode.h >index 73d23db82af25ea46c0f89785ce424bb60eb61a7..b6848c1e2de5dbe731533ee51c1c18c9faaa050e 100644 >--- a/Source/JavaScriptCore/parser/SourceCode.h >+++ b/Source/JavaScriptCore/parser/SourceCode.h >@@ -105,6 +105,9 @@ namespace JSC { > > SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn); > >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ SourceCode subArrowExpression(unsigned startArrowFunction, unsigned endArrowFunction, int firstLine, int startColumn, bool isEndByTerminator); >+#endif > private: > RefPtr<SourceProvider> m_provider; > int m_startChar; >@@ -117,6 +120,22 @@ namespace JSC { > { > return SourceCode(StringSourceProvider::create(source, url, startPosition), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()); > } >+ >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ inline SourceCode SourceCode::subArrowExpression(unsigned startArrowFunction, unsigned endArrowFunction, int firstLine, int startColumn, bool isEndByTerminator) >+ { >+ ASSERT(provider()->source()[startArrowFunction] == '=' && provider()->source()[startArrowFunction + 1] == '>'); >+ ASSERT(endArrowFunction >= 1); >+ >+ if (!isEndByTerminator && provider()->source().length() > endArrowFunction) { >+ UChar ch = provider()->source()[endArrowFunction - 1]; >+ ASSERT_UNUSED(ch, ch == ',' || ch == ';' || ch == ')' || ch == ']' || ch == '}'); >+ } >+ >+ startColumn += 1; // Convert to base 1. >+ return SourceCode(provider(), startArrowFunction, endArrowFunction, firstLine, startColumn); >+ } >+#endif > > inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn) > { >diff --git a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h >index 5e3fdffdda2a6c7d21ca43c6d552d99628d74187..b3df2f32ec246f3bdb44db3e9b59558634aabe1f 100644 >--- a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h >+++ b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h >@@ -35,14 +35,20 @@ namespace JSC { > > struct SourceProviderCacheItemCreationParameters { > unsigned functionNameStart; >- unsigned closeBraceLine; >- unsigned closeBraceOffset; >- unsigned closeBraceLineStartOffset; >+ unsigned endFunctionLine; >+ unsigned endFunctionStartOffset; >+ unsigned endFunctionEndOffset; >+ unsigned endFunctionLineStartOffset; > bool needsFullActivation; > bool usesEval; > bool strictMode; > Vector<RefPtr<UniquedStringImpl>> usedVariables; > Vector<RefPtr<UniquedStringImpl>> writtenVariables; >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ bool isBodyArrowExpression { false }; >+ JSTokenType tokenType { CLOSEBRACE }; >+ bool isPrevTerminator { false }; >+#endif > }; > > #if COMPILER(MSVC) >@@ -56,15 +62,19 @@ public: > static std::unique_ptr<SourceProviderCacheItem> create(const SourceProviderCacheItemCreationParameters&); > ~SourceProviderCacheItem(); > >- JSToken closeBraceToken() const >+ JSToken endFunctionToken() const > { > JSToken token; >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ token.m_type = isBodyArrowExpression ? tokenType : CLOSEBRACE; >+#else > token.m_type = CLOSEBRACE; >- token.m_data.offset = closeBraceOffset; >- token.m_location.startOffset = closeBraceOffset; >- token.m_location.endOffset = closeBraceOffset + 1; >- token.m_location.line = closeBraceLine; >- token.m_location.lineStartOffset = closeBraceLineStartOffset; >+#endif >+ token.m_data.offset = endFunctionStartOffset; >+ token.m_location.startOffset = endFunctionStartOffset; >+ token.m_location.endOffset = endFunctionEndOffset; >+ token.m_location.line = endFunctionLine; >+ token.m_location.lineStartOffset = endFunctionLineStartOffset; > // token.m_location.sourceOffset is initialized once by the client. So, > // we do not need to set it here. > return token; >@@ -73,18 +83,24 @@ public: > unsigned functionNameStart : 31; > bool needsFullActivation : 1; > >- unsigned closeBraceLine : 31; >+ unsigned endFunctionLine : 31; > bool usesEval : 1; > >- unsigned closeBraceOffset : 31; >+ unsigned endFunctionStartOffset : 31; >+ unsigned endFunctionEndOffset: 31; > bool strictMode : 1; > >- unsigned closeBraceLineStartOffset; >+ unsigned endFunctionLineStartOffset; > unsigned usedVariablesCount; > unsigned writtenVariablesCount; > > UniquedStringImpl** usedVariables() const { return const_cast<UniquedStringImpl**>(m_variables); } > UniquedStringImpl** writtenVariables() const { return const_cast<UniquedStringImpl**>(&m_variables[usedVariablesCount]); } >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ bool isBodyArrowExpression; >+ JSTokenType tokenType; >+ bool isPrevTerminator; >+#endif > > private: > SourceProviderCacheItem(const SourceProviderCacheItemCreationParameters&); >@@ -109,13 +125,19 @@ inline std::unique_ptr<SourceProviderCacheItem> SourceProviderCacheItem::create( > inline SourceProviderCacheItem::SourceProviderCacheItem(const SourceProviderCacheItemCreationParameters& parameters) > : functionNameStart(parameters.functionNameStart) > , needsFullActivation(parameters.needsFullActivation) >- , closeBraceLine(parameters.closeBraceLine) >+ , endFunctionLine(parameters.endFunctionLine) > , usesEval(parameters.usesEval) >- , closeBraceOffset(parameters.closeBraceOffset) >+ , endFunctionStartOffset(parameters.endFunctionStartOffset) >+ , endFunctionEndOffset(parameters.endFunctionEndOffset) > , strictMode(parameters.strictMode) >- , closeBraceLineStartOffset(parameters.closeBraceLineStartOffset) >+ , endFunctionLineStartOffset(parameters.endFunctionLineStartOffset) > , usedVariablesCount(parameters.usedVariables.size()) > , writtenVariablesCount(parameters.writtenVariables.size()) >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ , isBodyArrowExpression(parameters.isBodyArrowExpression) >+ , tokenType(parameters.tokenType) >+ , isPrevTerminator(parameters.isPrevTerminator) >+#endif > { > unsigned j = 0; > for (unsigned i = 0; i < usedVariablesCount; ++i, ++j) { >diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h >index be4621d37bc17cad5896b48d186df404e11bcc9c..7bee876ff65f1e3901e469d9db657d94e160577b 100644 >--- a/Source/JavaScriptCore/parser/SyntaxChecker.h >+++ b/Source/JavaScriptCore/parser/SyntaxChecker.h >@@ -179,6 +179,10 @@ public: > #endif > ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; } > int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind) { return FunctionBodyResult; } >+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX) >+ ExpressionType createArrowFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; } >+#endif >+ void setFunctionNameStart(int, int) { } > int createArguments() { return ArgumentsResult; } > int createArguments(int) { return ArgumentsResult; } > ExpressionType createSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return SpreadExpr; } >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 02f483022e16c3fe61d87f2ce54f205a72d04439..51ee9ee10ae7e58d0b8ed53f47575c32676465ed 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,40 @@ >+2015-06-23 Aleksandr Skachkov <gskachkov@gmail.com> >+ >+ [ES6] Implement ES6 arrow function syntax. Parser of arrow function with execution as common function >+ https://bugs.webkit.org/show_bug.cgi?id=144955 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Added arrow function tests >+ >+ * js/arrowfunction-asparamter-1-expected.txt: Added. >+ * js/arrowfunction-asparamter-1.html: Added. >+ * js/arrowfunction-asparamter-2-expected.txt: Added. >+ * js/arrowfunction-asparamter-2.html: Added. >+ * js/arrowfunction-associativity-1-expected.txt: Added. >+ * js/arrowfunction-associativity-1.html: Added. >+ * js/arrowfunction-associativity-2-expected.txt: Added. >+ * js/arrowfunction-associativity-2.html: Added. >+ * js/arrowfunction-block-1-expected.txt: Added. >+ * js/arrowfunction-block-1.html: Added. >+ * js/arrowfunction-block-2-expected.txt: Added. >+ * js/arrowfunction-block-2.html: Added. >+ * js/arrowfunction-syntax-endings-expected.txt: Added. >+ * js/arrowfunction-syntax-endings.html: Added. >+ * js/arrowfunction-syntax-errors-expected.txt: Added. >+ * js/arrowfunction-syntax-errors.html: Added. >+ * js/arrowfunction-syntax-expected.txt: Added. >+ * js/arrowfunction-syntax.html: Added. >+ * js/script-tests/arrowfunction-asparamter-1.js: Added. >+ * js/script-tests/arrowfunction-asparamter-2.js: Added. >+ * js/script-tests/arrowfunction-associativity-1.js: Added. >+ * js/script-tests/arrowfunction-associativity-2.js: Added. >+ * js/script-tests/arrowfunction-block-1.js: Added. >+ * js/script-tests/arrowfunction-block-2.js: Added. >+ * js/script-tests/arrowfunction-syntax-endings.js: Added. >+ * js/script-tests/arrowfunction-syntax-errors.js: Added. >+ * js/script-tests/arrowfunction-syntax.js: Added. >+ > 2015-06-22 Ryuan Choi <ryuan.choi@navercorp.com> > > [EFL] Hyphenation is not supported >diff --git a/LayoutTests/js/arrowfunction-asparamter-1-expected.txt b/LayoutTests/js/arrowfunction-asparamter-1-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..ff9ae39e9c9aeeed2a34ae29e3c0d08fad2b0250 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-asparamter-1-expected.txt >@@ -0,0 +1,10 @@ >+Tests for ES6 arrow function, passing arrow function as the paramter >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS "" + [1, 2, 3, 4].map(x => x, 32) is '1,2,3,4' >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/arrowfunction-asparamter-1.html b/LayoutTests/js/arrowfunction-asparamter-1.html >new file mode 100644 >index 0000000000000000000000000000000000000000..d1daf6a19ed78931adec3684d40e001c5971d1a9 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-asparamter-1.html >@@ -0,0 +1,10 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="script-tests/arrowfunction-asparamter-1.js"></script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/arrowfunction-asparamter-2-expected.txt b/LayoutTests/js/arrowfunction-asparamter-2-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..9acb0961c7aa5c207bd6b0781ddc460fd7ac6faf >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-asparamter-2-expected.txt >@@ -0,0 +1,11 @@ >+Tests for ES6 arrow function, passing arrow function as the paramter >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS f(x=>{return x * 25;}, 121) is 25*121 >+PASS f2((x, y)=>{return x * y;}, 14, 12) is 14*12 >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/arrowfunction-asparamter-2.html b/LayoutTests/js/arrowfunction-asparamter-2.html >new file mode 100644 >index 0000000000000000000000000000000000000000..07740db4f60046d2381a6efd7d11d0a320e8bb14 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-asparamter-2.html >@@ -0,0 +1,10 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="script-tests/arrowfunction-asparamter-2.js"></script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/arrowfunction-associativity-1-expected.txt b/LayoutTests/js/arrowfunction-associativity-1-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..3db2568fddba0a3f77072c3520ce22565cc700f1 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-associativity-1-expected.txt >@@ -0,0 +1,13 @@ >+Tests for ES6 arrow function nested declaration >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+af1 = af2 = af3 => af1 = af2 = af3 >+PASS af1 is af2 >+PASS af2 is 13 >+PASS af1 is 13 >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/arrowfunction-associativity-1.html b/LayoutTests/js/arrowfunction-associativity-1.html >new file mode 100644 >index 0000000000000000000000000000000000000000..8501f44ac51a03704f8b4917bf263170bcb69a4b >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-associativity-1.html >@@ -0,0 +1,10 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="script-tests/arrowfunction-associativity-1.js"></script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/arrowfunction-associativity-2-expected.txt b/LayoutTests/js/arrowfunction-associativity-2-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..e621a99da91320f5370f52677e49b2347e01610f >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-associativity-2-expected.txt >@@ -0,0 +1,11 @@ >+Tests for ES6 arrow function nested declaration >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+af = a => b => a >+PASS af('ABC')('DEF') is 'ABC' >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/arrowfunction-associativity-2.html b/LayoutTests/js/arrowfunction-associativity-2.html >new file mode 100644 >index 0000000000000000000000000000000000000000..924f5c1a2e91155f10a8a216a4f51c28d327a6b7 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-associativity-2.html >@@ -0,0 +1,10 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="script-tests/arrowfunction-associativity-2.js"></script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/arrowfunction-block-1-expected.txt b/LayoutTests/js/arrowfunction-block-1-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..799980413614de5b8f1c4e1b5591c92aff670a7c >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-block-1-expected.txt >@@ -0,0 +1,13 @@ >+Tests for ES6 arrow function declaration body as block >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+f = () => {} >+PASS typeof f() is 'undefined' >+g = () => ({}) >+PASS typeof g() is 'object' >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/arrowfunction-block-1.html b/LayoutTests/js/arrowfunction-block-1.html >new file mode 100644 >index 0000000000000000000000000000000000000000..1d66560c5a4e5c60e1b4be7254080eaf4f46e54f >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-block-1.html >@@ -0,0 +1,10 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="script-tests/arrowfunction-block-1.js"></script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/arrowfunction-block-2-expected.txt b/LayoutTests/js/arrowfunction-block-2-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..01e9f1043a95db6ee5bf203be17c7876a39e0996 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-block-2-expected.txt >@@ -0,0 +1,10 @@ >+Tests for ES6 arrow function declaration body as block >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS typeof af(0) is "undefined" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/arrowfunction-block-2.html b/LayoutTests/js/arrowfunction-block-2.html >new file mode 100644 >index 0000000000000000000000000000000000000000..8d05de697ad67f9937805120d5c1a207aee5239e >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-block-2.html >@@ -0,0 +1,10 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="script-tests/arrowfunction-block-2.js"></script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/arrowfunction-syntax-endings-expected.txt b/LayoutTests/js/arrowfunction-syntax-endings-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..50bd5b2271c8af3f4d18a4f42fd3e06ea17967e4 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-syntax-endings-expected.txt >@@ -0,0 +1,14 @@ >+Tests for ES6 arrow function endings >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS afEOL(12) is 13 >+PASS x=>x+1 did not throw exception. >+PASS x=>x+1 >+ did not throw exception. >+PASS f() is 39 >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/arrowfunction-syntax-endings.html b/LayoutTests/js/arrowfunction-syntax-endings.html >new file mode 100644 >index 0000000000000000000000000000000000000000..17c6d7d735f3098592f4b5852e4a76d1c81ca644 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-syntax-endings.html >@@ -0,0 +1,10 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="script-tests/arrowfunction-syntax-endings.js"></script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/arrowfunction-syntax-errors-expected.txt b/LayoutTests/js/arrowfunction-syntax-errors-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..a7479ac2ac3a2fecc9e5d352c88bd2e6b2918b50 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-syntax-errors-expected.txt >@@ -0,0 +1,123 @@ >+Tests for ES6 arrow function syntax errors >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS =>{} threw exception SyntaxError: Unexpected keyword '=>'. >+PASS x=> threw exception SyntaxError: Unexpected end of script. >+PASS x=>* threw exception SyntaxError: Unexpected token '*'. >+PASS x=>/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression.. >+PASS x=>% threw exception SyntaxError: Unexpected token '%'. >+PASS x=>+ threw exception SyntaxError: Unexpected end of script. >+PASS x=>- threw exception SyntaxError: Unexpected end of script. >+PASS x=><< threw exception SyntaxError: Unexpected token '<<'. >+PASS x=>>> threw exception SyntaxError: Unexpected token '>>'. >+PASS x=>>>> threw exception SyntaxError: Unexpected token '>>>'. >+PASS x=>< threw exception SyntaxError: Unexpected token '<'. >+PASS x=>> threw exception SyntaxError: Unexpected token '>'. >+PASS x=><= threw exception SyntaxError: Unexpected token '<='. >+PASS x=>>= threw exception SyntaxError: Unexpected token '>='. >+PASS x=>instanceof threw exception SyntaxError: Unexpected keyword 'instanceof'. >+PASS x=>in threw exception SyntaxError: Unexpected keyword 'in'. >+PASS x=>== threw exception SyntaxError: Unexpected token '=='. >+PASS x=>!= threw exception SyntaxError: Unexpected token '!='. >+PASS x=>=== threw exception SyntaxError: Unexpected token '==='. >+PASS x=>!== threw exception SyntaxError: Unexpected token '!=='. >+PASS x=>& threw exception SyntaxError: Unexpected token '&'. >+PASS x=>^ threw exception SyntaxError: Unexpected token '^'. >+PASS x=>| threw exception SyntaxError: Unexpected token '|'. >+PASS x=>&& threw exception SyntaxError: Unexpected token '&&'. >+PASS x=>|| threw exception SyntaxError: Unexpected token '||'. >+PASS x=>; threw exception SyntaxError: Unexpected token ';'. >+PASS x=>, threw exception SyntaxError: Unexpected token ','. >+PASS x=>{ threw exception SyntaxError: Unexpected end of script. >+PASS x=>{* threw exception SyntaxError: Unexpected token '*'. >+PASS x=>{/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression.. >+PASS x=>{% threw exception SyntaxError: Unexpected token '%'. >+PASS x=>{+ threw exception SyntaxError: Unexpected end of script. >+PASS x=>{- threw exception SyntaxError: Unexpected end of script. >+PASS x=>{<< threw exception SyntaxError: Unexpected token '<<'. >+PASS x=>{>> threw exception SyntaxError: Unexpected token '>>'. >+PASS x=>{>>> threw exception SyntaxError: Unexpected token '>>>'. >+PASS x=>{< threw exception SyntaxError: Unexpected token '<'. >+PASS x=>{> threw exception SyntaxError: Unexpected token '>'. >+PASS x=>{<= threw exception SyntaxError: Unexpected token '<='. >+PASS x=>{>= threw exception SyntaxError: Unexpected token '>='. >+PASS x=>{instanceof threw exception SyntaxError: Unexpected keyword 'instanceof'. >+PASS x=>{in threw exception SyntaxError: Unexpected keyword 'in'. >+PASS x=>{== threw exception SyntaxError: Unexpected token '=='. >+PASS x=>{!= threw exception SyntaxError: Unexpected token '!='. >+PASS x=>{=== threw exception SyntaxError: Unexpected token '==='. >+PASS x=>{!== threw exception SyntaxError: Unexpected token '!=='. >+PASS x=>{& threw exception SyntaxError: Unexpected token '&'. >+PASS x=>{^ threw exception SyntaxError: Unexpected token '^'. >+PASS x=>{| threw exception SyntaxError: Unexpected token '|'. >+PASS x=>{&& threw exception SyntaxError: Unexpected token '&&'. >+PASS x=>{|| threw exception SyntaxError: Unexpected token '||'. >+PASS x=>{; threw exception SyntaxError: Unexpected end of script. >+PASS x=>{, threw exception SyntaxError: Unexpected token ','. >+PASS x=>} threw exception SyntaxError: Unexpected token '}'. >+PASS var y = x=> threw exception SyntaxError: Unexpected end of script. >+PASS var y = x=>* threw exception SyntaxError: Unexpected token '*'. >+PASS var y = x=>/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression.. >+PASS var y = x=>% threw exception SyntaxError: Unexpected token '%'. >+PASS var y = x=>+ threw exception SyntaxError: Unexpected end of script. >+PASS var y = x=>- threw exception SyntaxError: Unexpected end of script. >+PASS var y = x=><< threw exception SyntaxError: Unexpected token '<<'. >+PASS var y = x=>>> threw exception SyntaxError: Unexpected token '>>'. >+PASS var y = x=>>>> threw exception SyntaxError: Unexpected token '>>>'. >+PASS var y = x=>< threw exception SyntaxError: Unexpected token '<'. >+PASS var y = x=>> threw exception SyntaxError: Unexpected token '>'. >+PASS var y = x=><= threw exception SyntaxError: Unexpected token '<='. >+PASS var y = x=>>= threw exception SyntaxError: Unexpected token '>='. >+PASS var y = x=>instanceof threw exception SyntaxError: Unexpected keyword 'instanceof'. >+PASS var y = x=>in threw exception SyntaxError: Unexpected keyword 'in'. >+PASS var y = x=>== threw exception SyntaxError: Unexpected token '=='. >+PASS var y = x=>!= threw exception SyntaxError: Unexpected token '!='. >+PASS var y = x=>=== threw exception SyntaxError: Unexpected token '==='. >+PASS var y = x=>!== threw exception SyntaxError: Unexpected token '!=='. >+PASS var y = x=>& threw exception SyntaxError: Unexpected token '&'. >+PASS var y = x=>^ threw exception SyntaxError: Unexpected token '^'. >+PASS var y = x=>| threw exception SyntaxError: Unexpected token '|'. >+PASS var y = x=>&& threw exception SyntaxError: Unexpected token '&&'. >+PASS var y = x=>|| threw exception SyntaxError: Unexpected token '||'. >+PASS var y = x=>; threw exception SyntaxError: Unexpected token ';'. >+PASS var y = x=>, threw exception SyntaxError: Unexpected token ','. >+PASS var y = x=>{ threw exception SyntaxError: Unexpected end of script. >+PASS var y = x=>{* threw exception SyntaxError: Unexpected token '*'. >+PASS var y = x=>{/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression.. >+PASS var y = x=>{% threw exception SyntaxError: Unexpected token '%'. >+PASS var y = x=>{+ threw exception SyntaxError: Unexpected end of script. >+PASS var y = x=>{- threw exception SyntaxError: Unexpected end of script. >+PASS var y = x=>{<< threw exception SyntaxError: Unexpected token '<<'. >+PASS var y = x=>{>> threw exception SyntaxError: Unexpected token '>>'. >+PASS var y = x=>{>>> threw exception SyntaxError: Unexpected token '>>>'. >+PASS var y = x=>{< threw exception SyntaxError: Unexpected token '<'. >+PASS var y = x=>{> threw exception SyntaxError: Unexpected token '>'. >+PASS var y = x=>{<= threw exception SyntaxError: Unexpected token '<='. >+PASS var y = x=>{>= threw exception SyntaxError: Unexpected token '>='. >+PASS var y = x=>{instanceof threw exception SyntaxError: Unexpected keyword 'instanceof'. >+PASS var y = x=>{in threw exception SyntaxError: Unexpected keyword 'in'. >+PASS var y = x=>{== threw exception SyntaxError: Unexpected token '=='. >+PASS var y = x=>{!= threw exception SyntaxError: Unexpected token '!='. >+PASS var y = x=>{=== threw exception SyntaxError: Unexpected token '==='. >+PASS var y = x=>{!== threw exception SyntaxError: Unexpected token '!=='. >+PASS var y = x=>{& threw exception SyntaxError: Unexpected token '&'. >+PASS var y = x=>{^ threw exception SyntaxError: Unexpected token '^'. >+PASS var y = x=>{| threw exception SyntaxError: Unexpected token '|'. >+PASS var y = x=>{&& threw exception SyntaxError: Unexpected token '&&'. >+PASS var y = x=>{|| threw exception SyntaxError: Unexpected token '||'. >+PASS var y = x=>{; threw exception SyntaxError: Unexpected end of script. >+PASS var y = x=>{, threw exception SyntaxError: Unexpected token ','. >+PASS var y = x=>} threw exception SyntaxError: Unexpected token '}'. >+PASS var t = x=>x+1; =>{} threw exception SyntaxError: Unexpected keyword '=>'. >+PASS [=>x+1] threw exception SyntaxError: Unexpected keyword '=>'. >+PASS [x=>x+1, =>x+1] threw exception SyntaxError: Unexpected keyword '=>'. >+PASS var f=>x+1; threw exception SyntaxError: Unexpected keyword '=>'. Expected ';' after var declaration.. >+PASS var x, y=>y+1; threw exception SyntaxError: Unexpected keyword '=>'. Expected ';' after var declaration.. >+PASS debug(=>x+1) threw exception SyntaxError: Unexpected keyword '=>'. >+PASS debug("xyz", =>x+1) threw exception SyntaxError: Unexpected keyword '=>'. >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/arrowfunction-syntax-errors.html b/LayoutTests/js/arrowfunction-syntax-errors.html >new file mode 100644 >index 0000000000000000000000000000000000000000..3744212e541437de7efee50d56032e242a78cce0 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-syntax-errors.html >@@ -0,0 +1,10 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="script-tests/arrowfunction-syntax-errors.js"></script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/arrowfunction-syntax-expected.txt b/LayoutTests/js/arrowfunction-syntax-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..7f21a41bbd5d8997c89020d509c9b72f4a7f1f5f >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-syntax-expected.txt >@@ -0,0 +1,42 @@ >+Tests for ES6 arrow function calling >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS af0(10) is 11 >+PASS af1(10) is 20 >+PASS af2(1212) is 1000 >+PASS af2_1(121) is a >+PASS af3(11,12) is 23 >+PASS afwrapper(x => 1234) is 1234 >+PASS afwrapper(x => 1234, 2345) is 1234 >+PASS afwrapper(x => 121 + 232) is 353 >+PASS afwrapper(x => 123 + 321, 9999) is 444 >+PASS afwrapper(x => x + 12, 21) is 33 >+PASS afwrapper((x) => x + 21, 32) is 53 >+PASS afwrapper(() => 100) is 100 >+PASS afwrapper(() => ext_value) is 121 >+PASS afwrapper(() => ext_value * 10) is 1210 >+PASS afwrapper((x) => ext_value * x, 30) is ext_value * 30 >+PASS afwrapper(() => 100, 11) is 100 >+PASS afwrapper(() => 100 + 10) is 110 >+PASS afwrapper(() => 100 + 11, 12) is 111 >+PASS arrowFunction4(1011) is 1012 >+PASS xyz1 is 10101 >+PASS afwrapper2((x, y) => x + y, 12 ,43) is 55 >+PASS afArr0[0](10) is 100 >+PASS afArr1[0](10) is 11 >+PASS afArr1[1](11) is 13 >+PASS afArr2[0](11) is 12 >+PASS afArr2[1](11) is 13 >+PASS afArr3[0](11) is 101 >+PASS afArr3[1](11) is 12323 >+PASS afObj.func(11) is 23 >+PASS afBlock0(11) is 1000 >+PASS afBlock1(11) is 1100 >+PASS afBlock2(11) is 2200 >+PASS afBlock3(11, 12222) is 134442 >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/js/arrowfunction-syntax.html b/LayoutTests/js/arrowfunction-syntax.html >new file mode 100644 >index 0000000000000000000000000000000000000000..ac632cba7ab92c77ad5fec6b942a67d86c48bcf4 >--- /dev/null >+++ b/LayoutTests/js/arrowfunction-syntax.html >@@ -0,0 +1,10 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="script-tests/arrowfunction-syntax.js"></script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/js/script-tests/arrowfunction-asparamter-1.js b/LayoutTests/js/script-tests/arrowfunction-asparamter-1.js >new file mode 100644 >index 0000000000000000000000000000000000000000..19e0a5035d269ae1b9a3f4f7ab162e90a74210f1 >--- /dev/null >+++ b/LayoutTests/js/script-tests/arrowfunction-asparamter-1.js >@@ -0,0 +1,5 @@ >+description('Tests for ES6 arrow function, passing arrow function as the paramter'); >+ >+shouldBe('"" + [1, 2, 3, 4].map(x => x, 32)', "'1,2,3,4'"); >+ >+var successfullyParsed = true; >diff --git a/LayoutTests/js/script-tests/arrowfunction-asparamter-2.js b/LayoutTests/js/script-tests/arrowfunction-asparamter-2.js >new file mode 100644 >index 0000000000000000000000000000000000000000..354567bdee37f769c0d581cf6932d3812ab12714 >--- /dev/null >+++ b/LayoutTests/js/script-tests/arrowfunction-asparamter-2.js >@@ -0,0 +1,9 @@ >+description('Tests for ES6 arrow function, passing arrow function as the paramter'); >+ >+var f = function (cl, paramter) { return cl(paramter); }; >+var f2 = function (cl, paramter1, paramter2) { return cl(paramter1, paramter2); }; >+ >+shouldBe('f(x=>{return x * 25;}, 121)', '25*121' ); >+shouldBe('f2((x, y)=>{return x * y;}, 14, 12)', '14*12'); >+ >+var successfullyParsed = true; >diff --git a/LayoutTests/js/script-tests/arrowfunction-associativity-1.js b/LayoutTests/js/script-tests/arrowfunction-associativity-1.js >new file mode 100644 >index 0000000000000000000000000000000000000000..38ee61bdc7ed61797cf88a54153804064fb6308d >--- /dev/null >+++ b/LayoutTests/js/script-tests/arrowfunction-associativity-1.js >@@ -0,0 +1,11 @@ >+description('Tests for ES6 arrow function nested declaration'); >+ >+var af1, af2, af3; >+af1 = af2 = af3 => af1 = af2 = af3; >+debug('af1 = af2 = af3 => af1 = af2 = af3') >+shouldBe('af1', 'af2'); >+af1(13); >+shouldBe('af2', '13'); >+shouldBe('af1', '13'); >+ >+var successfullyParsed = true; >diff --git a/LayoutTests/js/script-tests/arrowfunction-associativity-2.js b/LayoutTests/js/script-tests/arrowfunction-associativity-2.js >new file mode 100644 >index 0000000000000000000000000000000000000000..03d16a4391e9cc8c4dfecd789aa29596ee7cff53 >--- /dev/null >+++ b/LayoutTests/js/script-tests/arrowfunction-associativity-2.js >@@ -0,0 +1,8 @@ >+description('Tests for ES6 arrow function nested declaration'); >+ >+debug("af = a => b => a") >+var af = a => b => a; >+ >+shouldBe("af('ABC')('DEF')", "'ABC'"); >+ >+var successfullyParsed = true; >diff --git a/LayoutTests/js/script-tests/arrowfunction-block-1.js b/LayoutTests/js/script-tests/arrowfunction-block-1.js >new file mode 100644 >index 0000000000000000000000000000000000000000..ee7c12b5210fabcf3b44671c3440d7767e16795b >--- /dev/null >+++ b/LayoutTests/js/script-tests/arrowfunction-block-1.js >@@ -0,0 +1,11 @@ >+description('Tests for ES6 arrow function declaration body as block'); >+ >+debug('f = () => {}'); >+var f = () => {}; >+shouldBe("typeof f()", "'undefined'"); >+ >+debug('g = () => ({})'); >+var g = () => ({}); >+shouldBe("typeof g()", "'object'"); >+ >+var successfullyParsed = true; >diff --git a/LayoutTests/js/script-tests/arrowfunction-block-2.js b/LayoutTests/js/script-tests/arrowfunction-block-2.js >new file mode 100644 >index 0000000000000000000000000000000000000000..7535ed3ef8b3e5d143ee6c3cbcc2269e984d7ee4 >--- /dev/null >+++ b/LayoutTests/js/script-tests/arrowfunction-block-2.js >@@ -0,0 +1,7 @@ >+description('Tests for ES6 arrow function declaration body as block'); >+ >+var af = a => { a + 1; }; >+ >+shouldBe("typeof af(0)", '"undefined"'); >+ >+var successfullyParsed = true; >diff --git a/LayoutTests/js/script-tests/arrowfunction-syntax-endings.js b/LayoutTests/js/script-tests/arrowfunction-syntax-endings.js >new file mode 100644 >index 0000000000000000000000000000000000000000..74935e8955ca8351a55450112a727fd48f073179 >--- /dev/null >+++ b/LayoutTests/js/script-tests/arrowfunction-syntax-endings.js >@@ -0,0 +1,35 @@ >+description("Tests for ES6 arrow function endings"); >+ >+var afEOL = x=>x+1 >+result = afEOL(12); >+ >+shouldBe('afEOL(12)', '13'); >+ >+shouldNotThrow('x=>x+1'); >+ >+var afEOLTxt = 'x=>x+1' + String.fromCharCode(10); >+shouldNotThrow(afEOLTxt); >+ >+var f = function () { >+ var result = 0; >+ var afEOF; >+ >+ >+ afEOF = x => x*10000 + x*1000 - x*10000 - x*1000 + x >+ >+ >+ >+ result = afEOF(12); >+ >+ >+ result = result + afEOF(13); >+ >+ >+ result = result + afEOF(14); >+ >+ return result; >+}; >+ >+shouldBe('f()', '39'); >+ >+var successfullyParsed = true; >diff --git a/LayoutTests/js/script-tests/arrowfunction-syntax-errors.js b/LayoutTests/js/script-tests/arrowfunction-syntax-errors.js >new file mode 100644 >index 0000000000000000000000000000000000000000..14d1b6284082931d10adcf0b845d08a2de6d4762 >--- /dev/null >+++ b/LayoutTests/js/script-tests/arrowfunction-syntax-errors.js >@@ -0,0 +1,37 @@ >+description("Tests for ES6 arrow function syntax errors"); >+ >+shouldThrow('=>{}'); >+ >+function checkStatement(statement) { >+ var unexpectedSymbols = [ "", >+ "*", "/", "%" , "+", "-" , >+ "<<", ">>", ">>>" , >+ "<", ">", "<=", ">=", "instanceof", "in" , >+ "==", "!=", "===", "!==", >+ "&" , "^" , "|" , >+ "&&" , "||", ";" , "," >+ ]; >+ >+ for (var i = 0; i < unexpectedSymbols.length; i++) { >+ shouldThrow(statement + unexpectedSymbols[i]); >+ } >+} >+ >+checkStatement('x=>'); >+checkStatement('x=>{'); >+shouldThrow('x=>}'); >+ >+checkStatement('var y = x=>'); >+checkStatement('var y = x=>{'); >+shouldThrow('var y = x=>}'); >+ >+ >+shouldThrow('var t = x=>x+1; =>{}'); >+shouldThrow('[=>x+1]'); >+shouldThrow('[x=>x+1, =>x+1]'); >+shouldThrow('var f=>x+1;'); >+shouldThrow('var x, y=>y+1;'); >+shouldThrow('debug(=>x+1)'); >+shouldThrow('debug("xyz", =>x+1)'); >+ >+var successfullyParsed = true; >diff --git a/LayoutTests/js/script-tests/arrowfunction-syntax.js b/LayoutTests/js/script-tests/arrowfunction-syntax.js >new file mode 100644 >index 0000000000000000000000000000000000000000..c8066b7e66317e8c8275ec933a5714d2adc10f79 >--- /dev/null >+++ b/LayoutTests/js/script-tests/arrowfunction-syntax.js >@@ -0,0 +1,74 @@ >+description("Tests for ES6 arrow function calling"); >+ >+var af0 = v => v + 1; >+shouldBe('af0(10)', '11'); >+ >+var af1 = (v) => v * 2; >+shouldBe('af1(10)', '20'); >+ >+var af2 = () => 1000; >+shouldBe('af2(1212)', '1000' ); >+ >+var a = 151; >+var af2_1 = () => a; >+shouldBe('af2_1(121)', 'a'); >+ >+var af3 = (v, x) => v + x; >+shouldBe('af3(11,12)', '23'); >+ >+var afwrapper = function (cl, paramter) { return cl(paramter); }; >+ >+shouldBe('afwrapper(x => 1234)', '1234'); >+shouldBe('afwrapper(x => 1234, 2345)', '1234' ); >+shouldBe('afwrapper(x => 121 + 232)', '353' ); >+shouldBe('afwrapper(x => 123 + 321, 9999)', '444' ); >+shouldBe('afwrapper(x => x + 12, 21)', '33' ); >+shouldBe('afwrapper((x) => x + 21, 32)', '53'); >+shouldBe('afwrapper(() => 100)', '100'); >+ >+var ext_value = 121; >+shouldBe('afwrapper(() => ext_value)', '121'); >+shouldBe('afwrapper(() => ext_value * 10)', '1210'); >+shouldBe('afwrapper((x) => ext_value * x, 30)', 'ext_value * 30'); >+shouldBe('afwrapper(() => 100, 11)', '100' ); >+shouldBe('afwrapper(() => 100 + 10)', '110'); >+shouldBe('afwrapper(() => 100 + 11, 12)', '111' ); >+ >+var arrowFunction4 = v => v + 1, xyz1 = 10101; >+shouldBe('arrowFunction4(1011)', '1012'); >+shouldBe('xyz1', '10101'); >+ >+var afwrapper2 = function (cl, paramter1, paramter2) { return cl(paramter1, paramter2); }; >+shouldBe('afwrapper2((x, y) => x + y, 12 ,43)', '55'); >+ >+var afArr0 = [v => v * 10]; >+shouldBe('afArr0[0](10)', '100'); >+ >+var afArr1 = [v => v + 1, v => v + 2]; >+shouldBe('afArr1[0](10)', '11'); >+shouldBe('afArr1[1](11)', '13'); >+ >+var afArr2 = [(v) => v + 1, (v) => v + 2]; >+shouldBe('afArr2[0](11)', '12'); >+shouldBe('afArr2[1](11)', '13'); >+ >+var afArr3 = [() => 101, () => 12323]; >+shouldBe('afArr3[0](11)', '101'); >+shouldBe('afArr3[1](11)', '12323'); >+ >+var afObj = {func : y => y + 12}; >+shouldBe('afObj.func(11)', '23'); >+ >+var afBlock0 = () => { return 1000; }; >+shouldBe('afBlock0(11)', '1000'); >+ >+var afBlock1 = v => { var intval = 100; return v * intval; }; >+shouldBe('afBlock1(11)', '1100'); >+ >+var afBlock2 = (v) => { var int = 200; return v * int; }; >+shouldBe('afBlock2(11)', '2200'); >+ >+var afBlock3 = (v, x) => { var result = x * v; return result; }; >+shouldBe('afBlock3(11, 12222)', '134442'); >+ >+var successfullyParsed = true;
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 144955
:
253039
|
253069
|
253195
|
253296
|
253369
|
253378
|
254083
|
254087
|
254098
|
254114
|
254118
|
254166
|
254174
|
254209
|
254239
|
254438
|
254445
|
254763
|
255189
|
255191
|
255398
|
255400
|
255401
|
255426
|
255506
|
255586
|
255589
|
255593
|
255616
|
255617