Title: [196734] trunk
Revision
196734
Author
[email protected]
Date
2016-02-17 17:17:36 -0800 (Wed, 17 Feb 2016)

Log Message

Spread operator should be allowed when not the first argument of parameter list
https://bugs.webkit.org/show_bug.cgi?id=152721

Reviewed by Saam Barati.

Source/_javascript_Core:

Spread arguments to functions should now be ES6 compliant. Before we
would only take a spread operator if it was the sole argument to a
function. Additionally, we would not use the Symbol.iterator on the
object to generate the arguments. Instead we would do a loop up to the
length mapping indexed properties to the corresponding argument. We fix
both these issues by doing an AST transformation from foo(...a, b, ...c, d)
to foo(...[...a, b, ...c, d]) (where the spread on the rhs uses the
old spread semantics). This solution has the downside of requiring the
allocation of another object and copying each element twice but avoids a
large change to the vm calling convention.

* interpreter/Interpreter.cpp:
(JSC::loadVarargs):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createElementList):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseArguments):
(JSC::Parser<LexerType>::parseArgument):
(JSC::Parser<LexerType>::parseMemberExpression):
* parser/Parser.h:
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createElementList):
* tests/es6.yaml:
* tests/stress/spread-calling.js: Added.
(testFunction):
(testEmpty):
(makeObject):
(otherIterator.return.next):
(otherIterator):
(totalIter):
(throwingIter.return.next):
(throwingIter):
(i.catch):

LayoutTests:

Update tests with new semantics of spread calling. Additionally,
adjust benchmarks to run in a more reasonable time now that
spread is implemented correctly.

* js/basic-spread-expected.txt:
* js/parser-syntax-check-expected.txt:
* js/regress/script-tests/deltablue-varargs.js:
(deltaBlue):
* js/regress/script-tests/varargs-construct.js:
* js/script-tests/basic-spread.js:
* js/script-tests/parser-syntax-check.js:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (196733 => 196734)


--- trunk/LayoutTests/ChangeLog	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/LayoutTests/ChangeLog	2016-02-18 01:17:36 UTC (rev 196734)
@@ -1,3 +1,22 @@
+2016-02-17  Keith Miller  <[email protected]>
+
+        Spread operator should be allowed when not the first argument of parameter list
+        https://bugs.webkit.org/show_bug.cgi?id=152721
+
+        Reviewed by Saam Barati.
+
+        Update tests with new semantics of spread calling. Additionally,
+        adjust benchmarks to run in a more reasonable time now that
+        spread is implemented correctly.
+
+        * js/basic-spread-expected.txt:
+        * js/parser-syntax-check-expected.txt:
+        * js/regress/script-tests/deltablue-varargs.js:
+        (deltaBlue):
+        * js/regress/script-tests/varargs-construct.js:
+        * js/script-tests/basic-spread.js:
+        * js/script-tests/parser-syntax-check.js:
+
 2016-02-17  Ryan Haddad  <[email protected]>
 
         Add ios-simulator baseline for new W3C HTML tests added with r196710

Modified: trunk/LayoutTests/js/basic-spread-expected.txt (196733 => 196734)


--- trunk/LayoutTests/js/basic-spread-expected.txt	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/LayoutTests/js/basic-spread-expected.txt	2016-02-18 01:17:36 UTC (rev 196734)
@@ -43,46 +43,6 @@
 PASS args[1] is undefined
 PASS args[2] is null
 PASS args[3] is 4
-PASS passedThis is o
-PASS args[0] is 1
-PASS args[1] is undefined
-PASS args[2] is null
-PASS args[3] is 4
-PASS passedThis is o
-PASS args[0] is 1
-PASS args[1] is undefined
-PASS args[2] is null
-PASS args[3] is 4
-PASS passedThis is o
-PASS args[0] is 1
-PASS args[1] is undefined
-PASS args[2] is null
-PASS args[3] is 4
-PASS passedThis is o
-PASS args[0] is 1
-PASS args[1] is undefined
-PASS args[2] is null
-PASS args[3] is 4
-PASS passedThis is o
-PASS args[0] is 1
-PASS args[1] is undefined
-PASS args[2] is null
-PASS args[3] is 4
-PASS passedThis is o
-PASS args[0] is 1
-PASS args[1] is undefined
-PASS args[2] is null
-PASS args[3] is 4
-PASS passedThis is o
-PASS args[0] is 1
-PASS args[1] is undefined
-PASS args[2] is null
-PASS args[3] is 4
-PASS passedThis is o
-PASS args[0] is 1
-PASS args[1] is undefined
-PASS args[2] is null
-PASS args[3] is 4
 PASS a is [1,2,3]
 PASS [...a] is [1,2,3]
 PASS [...a] is [1,2,3]

Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (196733 => 196734)


--- trunk/LayoutTests/js/parser-syntax-check-expected.txt	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt	2016-02-18 01:17:36 UTC (rev 196734)
@@ -757,18 +757,18 @@
 PASS Invalid: "function f() { o.foo(bar...) }"
 PASS Invalid: "o[foo](bar...)"
 PASS Invalid: "function f() { o[foo](bar...) }"
-PASS Invalid: "foo(a,...bar)"
-PASS Invalid: "function f() { foo(a,...bar) }"
-PASS Invalid: "o.foo(a,...bar)"
-PASS Invalid: "function f() { o.foo(a,...bar) }"
-PASS Invalid: "o[foo](a,...bar)"
-PASS Invalid: "function f() { o[foo](a,...bar) }"
-PASS Invalid: "foo(...bar, a)"
-PASS Invalid: "function f() { foo(...bar, a) }"
-PASS Invalid: "o.foo(...bar, a)"
-PASS Invalid: "function f() { o.foo(...bar, a) }"
-PASS Invalid: "o[foo](...bar, a)"
-PASS Invalid: "function f() { o[foo](...bar, a) }"
+PASS Valid:   "foo(a,...bar)" with ReferenceError
+PASS Valid:   "function f() { foo(a,...bar) }"
+PASS Valid:   "o.foo(a,...bar)" with ReferenceError
+PASS Valid:   "function f() { o.foo(a,...bar) }"
+PASS Valid:   "o[foo](a,...bar)" with ReferenceError
+PASS Valid:   "function f() { o[foo](a,...bar) }"
+PASS Valid:   "foo(...bar, a)" with ReferenceError
+PASS Valid:   "function f() { foo(...bar, a) }"
+PASS Valid:   "o.foo(...bar, a)" with ReferenceError
+PASS Valid:   "function f() { o.foo(...bar, a) }"
+PASS Valid:   "o[foo](...bar, a)" with ReferenceError
+PASS Valid:   "function f() { o[foo](...bar, a) }"
 PASS Valid:   "[...bar]" with ReferenceError
 PASS Valid:   "function f() { [...bar] }"
 PASS Valid:   "[a, ...bar]" with ReferenceError

Modified: trunk/LayoutTests/js/regress/script-tests/deltablue-varargs.js (196733 => 196734)


--- trunk/LayoutTests/js/regress/script-tests/deltablue-varargs.js	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/LayoutTests/js/regress/script-tests/deltablue-varargs.js	2016-02-18 01:17:36 UTC (rev 196734)
@@ -880,9 +880,9 @@
 var planner = null;
 
 function deltaBlue() {
-  chainTest(...args(100));
-  projectionTest(...args(100));
+  chainTest(...args(25));
+  projectionTest(...args(25));
 }
 
-for (var i = 0; i < 30; ++i)
+for (var i = 0; i < 5; ++i)
     deltaBlue(...args());

Modified: trunk/LayoutTests/js/regress/script-tests/varargs-construct.js (196733 => 196734)


--- trunk/LayoutTests/js/regress/script-tests/varargs-construct.js	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/LayoutTests/js/regress/script-tests/varargs-construct.js	2016-02-18 01:17:36 UTC (rev 196734)
@@ -14,7 +14,7 @@
 
 noInline(bar);
 
-for (var i = 0; i < 1000000; ++i) {
+for (var i = 0; i < 100000; ++i) {
     var result = bar(1, 2);
     if (result.f != 1)
         throw "Error: bad result.f: " + result.f;

Modified: trunk/LayoutTests/js/script-tests/basic-spread.js (196733 => 196734)


--- trunk/LayoutTests/js/script-tests/basic-spread.js	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/LayoutTests/js/script-tests/basic-spread.js	2016-02-18 01:17:36 UTC (rev 196734)
@@ -17,18 +17,12 @@
 o.f = f;
 var test1 = [1, undefined, null, 4]
 var test2 = [1, , null, 4]
-var test3 = {length: 4, 0: 1, 2: null, 3: 4}
-var test4 = {length: 4, 0: 1, 1: undefined, 2: null, 3: 4}
 o.f(...test1)
 o.f(...test2)
-o.f(...test3)
-o.f(...test4)
 
 var h=eval('"f"')
 o[h](...test1)
 o[h](...test2)
-o[h](...test3)
-o[h](...test4)
 
 function g()
 {
@@ -37,13 +31,9 @@
 
 g.apply(null, test1)
 g.apply(null, test2)
-g.apply(null, test3)
-g.apply(null, test4)
 
 g(...test1)
 g(...test2)
-g(...test3)
-g(...test4)
 
 var a=[1,2,3]
 

Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (196733 => 196734)


--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js	2016-02-18 01:17:36 UTC (rev 196734)
@@ -471,12 +471,12 @@
 invalid("foo(bar...)")
 invalid("o.foo(bar...)")
 invalid("o[foo](bar...)")
-invalid("foo(a,...bar)")
-invalid("o.foo(a,...bar)")
-invalid("o[foo](a,...bar)")
-invalid("foo(...bar, a)")
-invalid("o.foo(...bar, a)")
-invalid("o[foo](...bar, a)")
+valid("foo(a,...bar)")
+valid("o.foo(a,...bar)")
+valid("o[foo](a,...bar)")
+valid("foo(...bar, a)")
+valid("o.foo(...bar, a)")
+valid("o[foo](...bar, a)")
 valid("[...bar]")
 valid("[a, ...bar]")
 valid("[...bar, a]")

Modified: trunk/Source/_javascript_Core/ChangeLog (196733 => 196734)


--- trunk/Source/_javascript_Core/ChangeLog	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-02-18 01:17:36 UTC (rev 196734)
@@ -1,3 +1,44 @@
+2016-02-17  Keith Miller  <[email protected]>
+
+        Spread operator should be allowed when not the first argument of parameter list
+        https://bugs.webkit.org/show_bug.cgi?id=152721
+
+        Reviewed by Saam Barati.
+
+        Spread arguments to functions should now be ES6 compliant. Before we
+        would only take a spread operator if it was the sole argument to a
+        function. Additionally, we would not use the Symbol.iterator on the
+        object to generate the arguments. Instead we would do a loop up to the
+        length mapping indexed properties to the corresponding argument. We fix
+        both these issues by doing an AST transformation from foo(...a, b, ...c, d)
+        to foo(...[...a, b, ...c, d]) (where the spread on the rhs uses the
+        old spread semantics). This solution has the downside of requiring the
+        allocation of another object and copying each element twice but avoids a
+        large change to the vm calling convention.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::loadVarargs):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createElementList):
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseArguments):
+        (JSC::Parser<LexerType>::parseArgument):
+        (JSC::Parser<LexerType>::parseMemberExpression):
+        * parser/Parser.h:
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createElementList):
+        * tests/es6.yaml:
+        * tests/stress/spread-calling.js: Added.
+        (testFunction):
+        (testEmpty):
+        (makeObject):
+        (otherIterator.return.next):
+        (otherIterator):
+        (totalIter):
+        (throwingIter.return.next):
+        (throwingIter):
+        (i.catch):
+
 2016-02-17  Brian Burg  <[email protected]>
 
         Remove a wrong cast in RemoteInspector::receivedSetupMessage

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (196733 => 196734)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-02-18 01:17:36 UTC (rev 196734)
@@ -247,7 +247,7 @@
 
 void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, JSValue arguments, uint32_t offset, uint32_t length)
 {
-    if (UNLIKELY(!arguments.isCell()))
+    if (UNLIKELY(!arguments.isCell()) || !length)
         return;
     
     JSCell* cell = arguments.asCell();

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (196733 => 196734)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2016-02-18 01:17:36 UTC (rev 196734)
@@ -441,6 +441,17 @@
 
     ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_parserArena) ElementNode(elisions, expr); }
     ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_parserArena) ElementNode(elems, elisions, expr); }
+    ElementNode* createElementList(ArgumentListNode* elems)
+    {
+        ElementNode* head = new (m_parserArena) ElementNode(0, elems->m_expr);
+        ElementNode* tail = head;
+        elems = elems->m_next;
+        while (elems) {
+            tail = new (m_parserArena) ElementNode(tail, 0, elems->m_expr);
+            elems = elems->m_next;
+        }
+        return head;
+    }
 
     FormalParameterList createFormalParameterList() { return new (m_parserArena) FunctionParameters(); }
     void appendParameter(FormalParameterList list, DestructuringPattern pattern, ExpressionNode* defaultValue) 

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (196733 => 196734)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2016-02-18 01:17:36 UTC (rev 196734)
@@ -3703,7 +3703,7 @@
 }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode)
+template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context)
 {
     consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list");
     JSTokenLocation location(tokenLocation());
@@ -3711,42 +3711,63 @@
         next(TreeBuilder::DontBuildStrings);
         return context.createArguments();
     }
-    if (match(DOTDOTDOT) && mode == AllowSpread) {
-        JSTokenLocation spreadLocation(tokenLocation());
-        auto start = m_token.m_startPosition;
-        auto divot = m_token.m_endPosition;
-        next();
-        auto spreadExpr = parseAssignmentExpression(context);
-        auto end = m_lastTokenEndPosition;
-        if (!spreadExpr)
-            failWithMessage("Cannot parse spread _expression_");
-        if (!consume(CLOSEPAREN)) {
-            if (match(COMMA))
-                semanticFail("Spread operator may only be applied to the last argument passed to a function");
-            handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
-        }
-        auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end);
-        TreeArgumentsList argList = context.createArgumentsList(location, spread);
-        return context.createArguments(argList);
-    }
-    TreeExpression firstArg = parseAssignmentExpression(context);
+    auto argumentsStart = m_token.m_startPosition;
+    auto argumentsDivot = m_token.m_endPosition;
+
+    ArgumentType argType = ArgumentType::Normal;
+    TreeExpression firstArg = parseArgument(context, argType);
     failIfFalse(firstArg, "Cannot parse function argument");
-    
+    semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target _expression_");
+
+    bool hasSpread = false;
+    if (argType == ArgumentType::Spread)
+        hasSpread = true;
     TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
     TreeArgumentsList tail = argList;
+
     while (match(COMMA)) {
         JSTokenLocation argumentLocation(tokenLocation());
         next(TreeBuilder::DontBuildStrings);
-        TreeExpression arg = parseAssignmentExpression(context);
-        failIfFalse(arg, "Cannot parse function argument");
+
+        TreeExpression arg = parseArgument(context, argType);
+        propagateError();
+        semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target _expression_");
+
+        if (argType == ArgumentType::Spread)
+            hasSpread = true;
+
         tail = context.createArgumentsList(argumentLocation, tail, arg);
     }
-    semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target _expression_");
+
     handleProductionOrFail(CLOSEPAREN, ")", "end", "argument list");
+    if (hasSpread) {
+        TreeExpression spreadArray = context.createSpreadExpression(location, context.createArray(location, context.createElementList(argList)), argumentsStart, argumentsDivot, m_lastTokenEndPosition);
+        return context.createArguments(context.createArgumentsList(location, spreadArray));
+    }
+
     return context.createArguments(argList);
 }
 
 template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArgument(TreeBuilder& context, ArgumentType& type)
+{
+    if (UNLIKELY(match(DOTDOTDOT))) {
+        JSTokenLocation spreadLocation(tokenLocation());
+        auto start = m_token.m_startPosition;
+        auto divot = m_token.m_endPosition;
+        next();
+        TreeExpression spreadExpr = parseAssignmentExpression(context);
+        propagateError();
+        auto end = m_lastTokenEndPosition;
+        type = ArgumentType::Spread;
+        return context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end);
+    }
+
+    type = ArgumentType::Normal;
+    return parseAssignmentExpression(context);
+}
+
+template <typename LexerType>
 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
 {
     TreeExpression base = 0;
@@ -3814,12 +3835,12 @@
             if (newCount) {
                 newCount--;
                 JSTextPosition expressionEnd = lastTokenEndPosition();
-                TreeArguments arguments = parseArguments(context, AllowSpread);
+                TreeArguments arguments = parseArguments(context);
                 failIfFalse(arguments, "Cannot parse call arguments");
                 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
             } else {
                 JSTextPosition expressionEnd = lastTokenEndPosition();
-                TreeArguments arguments = parseArguments(context, AllowSpread);
+                TreeArguments arguments = parseArguments(context);
                 failIfFalse(arguments, "Cannot parse call arguments");
                 if (baseIsSuper)
                     currentFunctionScope()->setHasDirectSuper();

Modified: trunk/Source/_javascript_Core/parser/Parser.h (196733 => 196734)


--- trunk/Source/_javascript_Core/parser/Parser.h	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2016-02-18 01:17:36 UTC (rev 196734)
@@ -677,6 +677,11 @@
     unsigned m_index;
 };
 
+enum class ArgumentType {
+    Normal,
+    Spread
+};
+
 template <typename LexerType>
 class Parser {
     WTF_MAKE_NONCOPYABLE(Parser);
@@ -1239,8 +1244,8 @@
     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
     template <class TreeBuilder> NEVER_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseFunctionExpression(TreeBuilder&);
-    enum SpreadMode { AllowSpread, DontAllowSpread };
-    template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&, SpreadMode);
+    template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArgument(TreeBuilder&, ArgumentType&);
     template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
     template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, bool isGenerator);
     template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind = ConstructorKind::None, SuperBinding = SuperBinding::NotNeeded);

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (196733 => 196734)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2016-02-18 01:17:36 UTC (rev 196734)
@@ -221,6 +221,7 @@
     int createPropertyList(const JSTokenLocation&, Property, int) { return PropertyListResult; }
     int createElementList(int, int) { return ElementsListResult; }
     int createElementList(int, int, int) { return ElementsListResult; }
+    int createElementList(int) { return ElementsListResult; }
     int createFormalParameterList() { return FormalParameterListResult; }
     void appendParameter(int, DestructuringPattern, int) { }
     int createClause(int, int) { return ClauseResult; }

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (196733 => 196734)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2016-02-18 01:05:56 UTC (rev 196733)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2016-02-18 01:17:36 UTC (rev 196734)
@@ -1113,11 +1113,11 @@
 - path: es6/Set_Set[Symbol.species].js
   cmd: runES6 :normal
 - path: es6/spread_..._operator_with_astral_plane_strings_in_function_calls.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/spread_..._operator_with_generator_instances_in_arrays.js
   cmd: runES6 :normal
 - path: es6/spread_..._operator_with_generator_instances_in_calls.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/spread_..._operator_with_generic_iterables_in_arrays.js
   cmd: runES6 :fail
 - path: es6/spread_..._operator_with_generic_iterables_in_calls.js
@@ -1127,7 +1127,7 @@
 - path: es6/spread_..._operator_with_instances_of_iterables_in_calls.js
   cmd: runES6 :fail
 - path: es6/spread_..._operator_with_strings_in_function_calls.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/typed_arrays_%TypedArray%.from.js
   cmd: runES6 :normal
 - path: es6/typed_arrays_%TypedArray%.of.js

Added: trunk/Source/_javascript_Core/tests/stress/spread-calling.js (0 => 196734)


--- trunk/Source/_javascript_Core/tests/stress/spread-calling.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/spread-calling.js	2016-02-18 01:17:36 UTC (rev 196734)
@@ -0,0 +1,81 @@
+function testFunction() {
+    if (arguments.length !== 10)
+        throw "wrong number of arguments expected 10 was " + arguments.length;
+    for (let i in arguments) {
+        if ((arguments[i] | 0) !== (i | 0))
+            throw "argument " + i + " expected " + i + " was " + arguments[i];
+    }
+}
+
+function testEmpty() {
+    if (arguments.length !== 0)
+        throw "wrong length expected 0 was " + arguments.length;
+}
+
+iter = Array.prototype.values;
+
+function makeObject(array, iterator) {
+    let obj = { [Symbol.iterator]: iterator, length: array.length };
+    for (let i in array)
+        obj[i] = array[i];
+    return obj;
+}
+
+function otherIterator() {
+    return {
+        count: 6,
+        next: function() {
+            if (this.count < 10)
+                return { value: this.count++, done: false };
+            return { done: true };
+        }
+    };
+}
+
+count = 0;
+function* totalIter() {
+    for (let i = count; i < count+5; i++) {
+        yield i;
+    }
+    count += 5;
+}
+
+function throwingIter() {
+     return {
+        count: 0,
+        next: function() {
+            if (this.count < 10)
+                return { value: this.count++, done: false };
+            throw new Error("this should have been caught");
+        }
+    };
+}
+
+object1 = makeObject([1, 2, 3], iter);
+object2 = makeObject([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], iter);
+object3 = makeObject([], otherIterator);
+object4 = makeObject([], totalIter);
+objectThrow = makeObject([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], throwingIter);
+
+for (let i = 0; i < 10000; i++) {
+    count = 0;
+    testFunction(0, ...[1, 2, 3], ...[4], 5, 6, ...[7, 8, 9]);
+    testFunction(...[0, 1], 2, 3, ...[4, 5, 6, 7, 8], 9);
+    testFunction(...[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+    testFunction(0, ...object1, 4, 5, ...[6, 7, 8, 9]);
+    testFunction(...object2);
+    testFunction(0, ...object1, 4, 5, ...object3);
+    testFunction(0, ..."12345", ...object3);
+    testEmpty(...[]);
+    testFunction(...object4, ...object4);
+    let failed = false;
+    try {
+        testFunction(...objectThrow);
+        failed = true;
+    } catch (e) {
+        if (!e instanceof Error)
+            failed = true;
+    }
+    if (failed)
+        throw "did not throw an exeption even though it should have";
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to