Changeset 196675 in webkit
- Timestamp:
- Feb 16, 2016 5:29:37 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r196673 r196675 1 2016-02-16 Keith Miller <keith_miller@apple.com> 2 3 Spread operator should be allowed when not the first argument of parameter list 4 https://bugs.webkit.org/show_bug.cgi?id=152721 5 6 Reviewed by Saam Barati. 7 8 Update tests with new semantics of spread calling. 9 10 * js/basic-spread-expected.txt: 11 * js/parser-syntax-check-expected.txt: 12 * js/script-tests/basic-spread.js: 13 * js/script-tests/parser-syntax-check.js: 14 1 15 2016-02-16 Chris Dumez <cdumez@apple.com> 2 16 -
trunk/LayoutTests/js/basic-spread-expected.txt
r157656 r196675 4 4 5 5 6 PASS passedThis is o7 PASS args[0] is 18 PASS args[1] is undefined9 PASS args[2] is null10 PASS args[3] is 411 PASS passedThis is o12 PASS args[0] is 113 PASS args[1] is undefined14 PASS args[2] is null15 PASS args[3] is 416 PASS passedThis is o17 PASS args[0] is 118 PASS args[1] is undefined19 PASS args[2] is null20 PASS args[3] is 421 PASS passedThis is o22 PASS args[0] is 123 PASS args[1] is undefined24 PASS args[2] is null25 PASS args[3] is 426 PASS passedThis is o27 PASS args[0] is 128 PASS args[1] is undefined29 PASS args[2] is null30 PASS args[3] is 431 PASS passedThis is o32 PASS args[0] is 133 PASS args[1] is undefined34 PASS args[2] is null35 PASS args[3] is 436 PASS passedThis is o37 PASS args[0] is 138 PASS args[1] is undefined39 PASS args[2] is null40 PASS args[3] is 441 PASS passedThis is o42 PASS args[0] is 143 PASS args[1] is undefined44 PASS args[2] is null45 PASS args[3] is 446 6 PASS passedThis is o 47 7 PASS args[0] is 1 -
trunk/LayoutTests/js/parser-syntax-check-expected.txt
r192671 r196675 758 758 PASS Invalid: "o[foo](bar...)" 759 759 PASS Invalid: "function f() { o[foo](bar...) }" 760 PASS Invalid: "foo(a,...bar)"761 PASS Invalid:"function f() { foo(a,...bar) }"762 PASS Invalid: "o.foo(a,...bar)"763 PASS Invalid:"function f() { o.foo(a,...bar) }"764 PASS Invalid: "o[foo](a,...bar)"765 PASS Invalid:"function f() { o[foo](a,...bar) }"766 PASS Invalid: "foo(...bar, a)"767 PASS Invalid:"function f() { foo(...bar, a) }"768 PASS Invalid: "o.foo(...bar, a)"769 PASS Invalid:"function f() { o.foo(...bar, a) }"770 PASS Invalid: "o[foo](...bar, a)"771 PASS Invalid:"function f() { o[foo](...bar, a) }"760 PASS Valid: "foo(a,...bar)" with ReferenceError 761 PASS Valid: "function f() { foo(a,...bar) }" 762 PASS Valid: "o.foo(a,...bar)" with ReferenceError 763 PASS Valid: "function f() { o.foo(a,...bar) }" 764 PASS Valid: "o[foo](a,...bar)" with ReferenceError 765 PASS Valid: "function f() { o[foo](a,...bar) }" 766 PASS Valid: "foo(...bar, a)" with ReferenceError 767 PASS Valid: "function f() { foo(...bar, a) }" 768 PASS Valid: "o.foo(...bar, a)" with ReferenceError 769 PASS Valid: "function f() { o.foo(...bar, a) }" 770 PASS Valid: "o[foo](...bar, a)" with ReferenceError 771 PASS Valid: "function f() { o[foo](...bar, a) }" 772 772 PASS Valid: "[...bar]" with ReferenceError 773 773 PASS Valid: "function f() { [...bar] }" -
trunk/LayoutTests/js/script-tests/basic-spread.js
r157656 r196675 18 18 var test1 = [1, undefined, null, 4] 19 19 var test2 = [1, , null, 4] 20 var test3 = {length: 4, 0: 1, 2: null, 3: 4}21 var test4 = {length: 4, 0: 1, 1: undefined, 2: null, 3: 4}22 20 o.f(...test1) 23 21 o.f(...test2) 24 o.f(...test3)25 o.f(...test4)26 22 27 23 var h=eval('"f"') 28 24 o[h](...test1) 29 25 o[h](...test2) 30 o[h](...test3)31 o[h](...test4)32 26 33 27 function g() … … 38 32 g.apply(null, test1) 39 33 g.apply(null, test2) 40 g.apply(null, test3)41 g.apply(null, test4)42 34 43 35 g(...test1) 44 36 g(...test2) 45 g(...test3)46 g(...test4)47 37 48 38 var a=[1,2,3] -
trunk/LayoutTests/js/script-tests/parser-syntax-check.js
r192671 r196675 472 472 invalid("o.foo(bar...)") 473 473 invalid("o[foo](bar...)") 474 invalid("foo(a,...bar)")475 invalid("o.foo(a,...bar)")476 invalid("o[foo](a,...bar)")477 invalid("foo(...bar, a)")478 invalid("o.foo(...bar, a)")479 invalid("o[foo](...bar, a)")474 valid("foo(a,...bar)") 475 valid("o.foo(a,...bar)") 476 valid("o[foo](a,...bar)") 477 valid("foo(...bar, a)") 478 valid("o.foo(...bar, a)") 479 valid("o[foo](...bar, a)") 480 480 valid("[...bar]") 481 481 valid("[a, ...bar]") -
trunk/Source/JavaScriptCore/ChangeLog
r196672 r196675 1 2016-02-16 Keith Miller <keith_miller@apple.com> 2 3 Spread operator should be allowed when not the first argument of parameter list 4 https://bugs.webkit.org/show_bug.cgi?id=152721 5 6 Reviewed by Saam Barati. 7 8 Spread arguments to functions should now be ES6 compliant. Before we 9 would only take a spread operator if it was the sole argument to a 10 function. Additionally, we would not use the Symbol.iterator on the 11 object to generate the arguments. Instead we would do a loop up to the 12 length mapping indexed properties to the corresponding argument. We fix 13 both these issues by doing an AST transformation from foo(...a, b, ...c, d) 14 to foo(...[...a, b, ...c, d]) (where the spread on the rhs uses the 15 old spread semantics). This solution has the downside of requiring the 16 allocation of another object and copying each element twice but avoids a 17 large change to the vm calling convention. 18 19 * interpreter/Interpreter.cpp: 20 (JSC::loadVarargs): 21 * parser/ASTBuilder.h: 22 (JSC::ASTBuilder::createElementList): 23 * parser/Parser.cpp: 24 (JSC::Parser<LexerType>::parseArguments): 25 (JSC::Parser<LexerType>::parseArgument): 26 (JSC::Parser<LexerType>::parseMemberExpression): 27 * parser/Parser.h: 28 * parser/SyntaxChecker.h: 29 (JSC::SyntaxChecker::createElementList): 30 * tests/es6.yaml: 31 * tests/stress/spread-calling.js: Added. 32 (testFunction): 33 (testEmpty): 34 (makeObject): 35 (otherIterator.return.next): 36 (otherIterator): 37 (totalIter): 38 (throwingIter.return.next): 39 (throwingIter): 40 (i.catch): 41 1 42 2016-02-16 Benjamin Poulain <bpoulain@apple.com> 2 43 -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r194835 r196675 248 248 void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, JSValue arguments, uint32_t offset, uint32_t length) 249 249 { 250 if (UNLIKELY(!arguments.isCell()) )250 if (UNLIKELY(!arguments.isCell()) || !length) 251 251 return; 252 252 -
trunk/Source/JavaScriptCore/parser/ASTBuilder.h
r196587 r196675 442 442 ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_parserArena) ElementNode(elisions, expr); } 443 443 ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_parserArena) ElementNode(elems, elisions, expr); } 444 ElementNode* createElementList(ArgumentListNode* elems) 445 { 446 ElementNode* head = new (m_parserArena) ElementNode(0, elems->m_expr); 447 ElementNode* tail = head; 448 elems = elems->m_next; 449 while (elems) { 450 tail = new (m_parserArena) ElementNode(tail, 0, elems->m_expr); 451 elems = elems->m_next; 452 } 453 return head; 454 } 444 455 445 456 FormalParameterList createFormalParameterList() { return new (m_parserArena) FunctionParameters(); } -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r196587 r196675 3704 3704 3705 3705 template <typename LexerType> 3706 template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context , SpreadMode mode)3706 template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context) 3707 3707 { 3708 3708 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list"); … … 3712 3712 return context.createArguments(); 3713 3713 } 3714 if (match(DOTDOTDOT) && mode == AllowSpread) { 3714 auto argumentsStart = m_token.m_startPosition; 3715 auto argumentsDivot = m_token.m_endPosition; 3716 3717 ArgumentType argType = ArgumentType::Normal; 3718 TreeExpression firstArg = parseArgument(context, argType); 3719 failIfFalse(firstArg, "Cannot parse function argument"); 3720 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression"); 3721 3722 bool hasSpread = false; 3723 if (argType == ArgumentType::Spread) 3724 hasSpread = true; 3725 TreeArgumentsList argList = context.createArgumentsList(location, firstArg); 3726 TreeArgumentsList tail = argList; 3727 3728 while (match(COMMA)) { 3729 JSTokenLocation argumentLocation(tokenLocation()); 3730 next(TreeBuilder::DontBuildStrings); 3731 3732 TreeExpression arg = parseArgument(context, argType); 3733 propagateError(); 3734 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression"); 3735 3736 if (argType == ArgumentType::Spread) 3737 hasSpread = true; 3738 3739 tail = context.createArgumentsList(argumentLocation, tail, arg); 3740 } 3741 3742 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list"); 3743 if (hasSpread) { 3744 TreeExpression spreadArray = context.createSpreadExpression(location, context.createArray(location, context.createElementList(argList)), argumentsStart, argumentsDivot, m_lastTokenEndPosition); 3745 return context.createArguments(context.createArgumentsList(location, spreadArray)); 3746 } 3747 3748 return context.createArguments(argList); 3749 } 3750 3751 template <typename LexerType> 3752 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArgument(TreeBuilder& context, ArgumentType& type) 3753 { 3754 if (UNLIKELY(match(DOTDOTDOT))) { 3715 3755 JSTokenLocation spreadLocation(tokenLocation()); 3716 3756 auto start = m_token.m_startPosition; 3717 3757 auto divot = m_token.m_endPosition; 3718 3758 next(); 3719 auto spreadExpr = parseAssignmentExpression(context); 3759 TreeExpression spreadExpr = parseAssignmentExpression(context); 3760 propagateError(); 3720 3761 auto end = m_lastTokenEndPosition; 3721 if (!spreadExpr) 3722 failWithMessage("Cannot parse spread expression"); 3723 if (!consume(CLOSEPAREN)) { 3724 if (match(COMMA)) 3725 semanticFail("Spread operator may only be applied to the last argument passed to a function"); 3726 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list"); 3727 } 3728 auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end); 3729 TreeArgumentsList argList = context.createArgumentsList(location, spread); 3730 return context.createArguments(argList); 3731 } 3732 TreeExpression firstArg = parseAssignmentExpression(context); 3733 failIfFalse(firstArg, "Cannot parse function argument"); 3734 3735 TreeArgumentsList argList = context.createArgumentsList(location, firstArg); 3736 TreeArgumentsList tail = argList; 3737 while (match(COMMA)) { 3738 JSTokenLocation argumentLocation(tokenLocation()); 3739 next(TreeBuilder::DontBuildStrings); 3740 TreeExpression arg = parseAssignmentExpression(context); 3741 failIfFalse(arg, "Cannot parse function argument"); 3742 tail = context.createArgumentsList(argumentLocation, tail, arg); 3743 } 3744 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression"); 3745 handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list"); 3746 return context.createArguments(argList); 3762 type = ArgumentType::Spread; 3763 return context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end); 3764 } 3765 3766 type = ArgumentType::Normal; 3767 return parseAssignmentExpression(context); 3747 3768 } 3748 3769 … … 3815 3836 newCount--; 3816 3837 JSTextPosition expressionEnd = lastTokenEndPosition(); 3817 TreeArguments arguments = parseArguments(context , AllowSpread);3838 TreeArguments arguments = parseArguments(context); 3818 3839 failIfFalse(arguments, "Cannot parse call arguments"); 3819 3840 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition()); 3820 3841 } else { 3821 3842 JSTextPosition expressionEnd = lastTokenEndPosition(); 3822 TreeArguments arguments = parseArguments(context , AllowSpread);3843 TreeArguments arguments = parseArguments(context); 3823 3844 failIfFalse(arguments, "Cannot parse call arguments"); 3824 3845 if (baseIsSuper) -
trunk/Source/JavaScriptCore/parser/Parser.h
r196545 r196675 676 676 ScopeStack* m_scopeStack; 677 677 unsigned m_index; 678 }; 679 680 enum class ArgumentType { 681 Normal, 682 Spread 678 683 }; 679 684 … … 1240 1245 template <class TreeBuilder> NEVER_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&); 1241 1246 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseFunctionExpression(TreeBuilder&); 1242 enum SpreadMode { AllowSpread, DontAllowSpread };1243 template <class TreeBuilder> ALWAYS_INLINE Tree Arguments parseArguments(TreeBuilder&, SpreadMode);1247 template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&); 1248 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArgument(TreeBuilder&, ArgumentType&); 1244 1249 template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict); 1245 1250 template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, bool isGenerator); -
trunk/Source/JavaScriptCore/parser/SyntaxChecker.h
r196022 r196675 222 222 int createElementList(int, int) { return ElementsListResult; } 223 223 int createElementList(int, int, int) { return ElementsListResult; } 224 int createElementList(int) { return ElementsListResult; } 224 225 int createFormalParameterList() { return FormalParameterListResult; } 225 226 void appendParameter(int, DestructuringPattern, int) { } -
trunk/Source/JavaScriptCore/tests/es6.yaml
r196498 r196675 1114 1114 cmd: runES6 :normal 1115 1115 - path: es6/spread_..._operator_with_astral_plane_strings_in_function_calls.js 1116 cmd: runES6 : fail1116 cmd: runES6 :normal 1117 1117 - path: es6/spread_..._operator_with_generator_instances_in_arrays.js 1118 1118 cmd: runES6 :normal 1119 1119 - path: es6/spread_..._operator_with_generator_instances_in_calls.js 1120 cmd: runES6 : fail1120 cmd: runES6 :normal 1121 1121 - path: es6/spread_..._operator_with_generic_iterables_in_arrays.js 1122 1122 cmd: runES6 :fail … … 1128 1128 cmd: runES6 :fail 1129 1129 - path: es6/spread_..._operator_with_strings_in_function_calls.js 1130 cmd: runES6 : fail1130 cmd: runES6 :normal 1131 1131 - path: es6/typed_arrays_%TypedArray%.from.js 1132 1132 cmd: runES6 :normal
Note: See TracChangeset
for help on using the changeset viewer.