Index: test/webkit/fast/js/function-toString-parentheses.js |
diff --git a/test/webkit/fast/js/function-toString-parentheses.js b/test/webkit/fast/js/function-toString-parentheses.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6bc62ab811a2b539c3527dcb7165118866808951 |
--- /dev/null |
+++ b/test/webkit/fast/js/function-toString-parentheses.js |
@@ -0,0 +1,234 @@ |
+// Copyright 2013 the V8 project authors. All rights reserved. |
+// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
+// |
+// Redistribution and use in source and binary forms, with or without |
+// modification, are permitted provided that the following conditions |
+// are met: |
+// 1. Redistributions of source code must retain the above copyright |
+// notice, this list of conditions and the following disclaimer. |
+// 2. Redistributions in binary form must reproduce the above copyright |
+// notice, this list of conditions and the following disclaimer in the |
+// documentation and/or other materials provided with the distribution. |
+// |
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY |
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
+// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
+// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+description( |
+"This test checks that parentheses are preserved when significant, and not added where inappropriate. " + |
+"We need this test because the JavaScriptCore parser removes all parentheses and the serializer then adds them back." |
+); |
+ |
+function compileAndSerialize(expression) |
+{ |
+ var f = eval("(function () { return " + expression + "; })"); |
+ var serializedString = f.toString(); |
+ serializedString = serializedString.replace(/[ \t\r\n]+/g, " "); |
+ serializedString = serializedString.replace("function () { return ", ""); |
+ serializedString = serializedString.replace("; }", ""); |
+ return serializedString; |
+} |
+ |
+function compileAndSerializeLeftmostTest(expression) |
+{ |
+ var f = eval("(function () { " + expression + "; })"); |
+ var serializedString = f.toString(); |
+ serializedString = serializedString.replace(/[ \t\r\n]+/g, " "); |
+ serializedString = serializedString.replace("function () { ", ""); |
+ serializedString = serializedString.replace("; }", ""); |
+ return serializedString; |
+} |
+ |
+var removesExtraParentheses = compileAndSerialize("(a + b) + c") == "a + b + c"; |
+ |
+function testKeepParentheses(expression) |
+{ |
+ shouldBe("compileAndSerialize('" + expression + "')", |
+ "'" + expression + "'"); |
+} |
+ |
+function testOptionalParentheses(expression) |
+{ |
+ stripped_expression = removesExtraParentheses |
+ ? expression.replace(/\(/g, '').replace(/\)/g, '') |
+ : expression; |
+ shouldBe("compileAndSerialize('" + expression + "')", |
+ "'" + stripped_expression + "'"); |
+} |
+ |
+function testLeftAssociativeSame(opA, opB) |
+{ |
+ testKeepParentheses("a " + opA + " b " + opB + " c"); |
+ testOptionalParentheses("(a " + opA + " b) " + opB + " c"); |
+ testKeepParentheses("a " + opA + " (b " + opB + " c)"); |
+} |
+ |
+function testRightAssociativeSame(opA, opB) |
+{ |
+ testKeepParentheses("a " + opA + " b " + opB + " c"); |
+ testKeepParentheses("(a " + opA + " b) " + opB + " c"); |
+ testOptionalParentheses("a " + opA + " (b " + opB + " c)"); |
+} |
+ |
+function testHigherFirst(opHigher, opLower) |
+{ |
+ testKeepParentheses("a " + opHigher + " b " + opLower + " c"); |
+ testOptionalParentheses("(a " + opHigher + " b) " + opLower + " c"); |
+ testKeepParentheses("a " + opHigher + " (b " + opLower + " c)"); |
+} |
+ |
+function testLowerFirst(opLower, opHigher) |
+{ |
+ testKeepParentheses("a " + opLower + " b " + opHigher + " c"); |
+ testKeepParentheses("(a " + opLower + " b) " + opHigher + " c"); |
+ testOptionalParentheses("a " + opLower + " (b " + opHigher + " c)"); |
+} |
+ |
+var binaryOperators = [ |
+ [ "*", "/", "%" ], [ "+", "-" ], |
+ [ "<<", ">>", ">>>" ], |
+ [ "<", ">", "<=", ">=", "instanceof", "in" ], |
+ [ "==", "!=", "===", "!==" ], |
+ [ "&" ], [ "^" ], [ "|" ], |
+ [ "&&" ], [ "||" ] |
+]; |
+ |
+for (i = 0; i < binaryOperators.length; ++i) { |
+ var ops = binaryOperators[i]; |
+ for (j = 0; j < ops.length; ++j) { |
+ var op = ops[j]; |
+ testLeftAssociativeSame(op, op); |
+ if (j != 0) |
+ testLeftAssociativeSame(ops[0], op); |
+ if (i < binaryOperators.length - 1) { |
+ var nextOps = binaryOperators[i + 1]; |
+ if (j == 0) |
+ for (k = 0; k < nextOps.length; ++k) |
+ testHigherFirst(op, nextOps[k]); |
+ else |
+ testHigherFirst(op, nextOps[0]); |
+ } |
+ } |
+} |
+ |
+var assignmentOperators = [ "=", "*=", "/=" , "%=", "+=", "-=", "<<=", ">>=", ">>>=", "&=", "^=", "|=" ]; |
+ |
+for (i = 0; i < assignmentOperators.length; ++i) { |
+ var op = assignmentOperators[i]; |
+ testRightAssociativeSame(op, op); |
+ if (i != 0) |
+ testRightAssociativeSame("=", op); |
+ testLowerFirst(op, "+"); |
+ shouldThrow("compileAndSerialize('a + b " + op + " c')"); |
+ testKeepParentheses("(a + b) " + op + " c"); |
+ testKeepParentheses("a + (b " + op + " c)"); |
+} |
+ |
+var prefixOperators = [ "delete", "void", "typeof", "++", "--", "+", "-", "~", "!" ]; |
+var prefixOperatorSpace = [ " ", " ", " ", "", "", " ", " ", "", "" ]; |
+ |
+for (i = 0; i < prefixOperators.length; ++i) { |
+ var op = prefixOperators[i] + prefixOperatorSpace[i]; |
+ testKeepParentheses("" + op + "a + b"); |
+ testOptionalParentheses("(" + op + "a) + b"); |
+ testKeepParentheses("" + op + "(a + b)"); |
+ testKeepParentheses("!" + op + "a"); |
+ testOptionalParentheses("!(" + op + "a)"); |
+} |
+ |
+ |
+testKeepParentheses("!a++"); |
+testOptionalParentheses("!(a++)"); |
+testKeepParentheses("(!a)++"); |
+ |
+testKeepParentheses("!a--"); |
+testOptionalParentheses("!(a--)"); |
+testKeepParentheses("(!a)--"); |
+ |
+testKeepParentheses("(-1)[a]"); |
+testKeepParentheses("(-1)[a] = b"); |
+testKeepParentheses("(-1)[a] += b"); |
+testKeepParentheses("(-1)[a]++"); |
+testKeepParentheses("++(-1)[a]"); |
+testKeepParentheses("(-1)[a]()"); |
+ |
+testKeepParentheses("new (-1)()"); |
+ |
+testKeepParentheses("(-1).a"); |
+testKeepParentheses("(-1).a = b"); |
+testKeepParentheses("(-1).a += b"); |
+testKeepParentheses("(-1).a++"); |
+testKeepParentheses("++(-1).a"); |
+testKeepParentheses("(-1).a()"); |
+ |
+testKeepParentheses("(- 0)[a]"); |
+testKeepParentheses("(- 0)[a] = b"); |
+testKeepParentheses("(- 0)[a] += b"); |
+testKeepParentheses("(- 0)[a]++"); |
+testKeepParentheses("++(- 0)[a]"); |
+testKeepParentheses("(- 0)[a]()"); |
+ |
+testKeepParentheses("new (- 0)()"); |
+ |
+testKeepParentheses("(- 0).a"); |
+testKeepParentheses("(- 0).a = b"); |
+testKeepParentheses("(- 0).a += b"); |
+testKeepParentheses("(- 0).a++"); |
+testKeepParentheses("++(- 0).a"); |
+testKeepParentheses("(- 0).a()"); |
+ |
+testOptionalParentheses("(1)[a]"); |
+testOptionalParentheses("(1)[a] = b"); |
+testOptionalParentheses("(1)[a] += b"); |
+testOptionalParentheses("(1)[a]++"); |
+testOptionalParentheses("++(1)[a]"); |
+ |
+shouldBe("compileAndSerialize('(1)[a]()')", |
+ removesExtraParentheses ? "'1[a]()'" : "'(1)[a]()'"); |
+ |
+shouldBe("compileAndSerialize('new (1)()')", |
+ removesExtraParentheses ? "'new 1()'" : "'new (1)()'"); |
+ |
+testKeepParentheses("(1).a"); |
+testKeepParentheses("(1).a = b"); |
+testKeepParentheses("(1).a += b"); |
+testKeepParentheses("(1).a++"); |
+testKeepParentheses("++(1).a"); |
+testKeepParentheses("(1).a()"); |
+ |
+for (i = 0; i < assignmentOperators.length; ++i) { |
+ var op = assignmentOperators[i]; |
+ testKeepParentheses("(-1) " + op + " a"); |
+ testKeepParentheses("(- 0) " + op + " a"); |
+ testKeepParentheses("1 " + op + " a"); |
+} |
+ |
+shouldBe("compileAndSerializeLeftmostTest('({ }).x')", "'({ }).x'"); |
+shouldBe("compileAndSerializeLeftmostTest('x = { }')", "'x = { }'"); |
+shouldBe("compileAndSerializeLeftmostTest('(function () { })()')", "'(function () { })()'"); |
+shouldBe("compileAndSerializeLeftmostTest('x = function () { }')", "'x = function () { }'"); |
+ |
+shouldBe("compileAndSerializeLeftmostTest('var a')", "'var a'"); |
+shouldBe("compileAndSerializeLeftmostTest('var a = 1')", "'var a = 1'"); |
+shouldBe("compileAndSerializeLeftmostTest('var a, b')", "'var a, b'"); |
+shouldBe("compileAndSerializeLeftmostTest('var a = 1, b = 2')", "'var a = 1, b = 2'"); |
+shouldBe("compileAndSerializeLeftmostTest('var a, b, c')", "'var a, b, c'"); |
+shouldBe("compileAndSerializeLeftmostTest('var a = 1, b = 2, c = 3')", "'var a = 1, b = 2, c = 3'"); |
+ |
+shouldBe("compileAndSerializeLeftmostTest('const a = 1')", "'const a = 1'"); |
+shouldBe("compileAndSerializeLeftmostTest('const a = (1, 2)')", "'const a = (1, 2)'"); |
+shouldBe("compileAndSerializeLeftmostTest('const a, b = 1')", "'const a, b = 1'"); |
+shouldBe("compileAndSerializeLeftmostTest('const a = 1, b')", "'const a = 1, b'"); |
+shouldBe("compileAndSerializeLeftmostTest('const a = 1, b = 1')", "'const a = 1, b = 1'"); |
+shouldBe("compileAndSerializeLeftmostTest('const a = (1, 2), b = 1')", "'const a = (1, 2), b = 1'"); |
+shouldBe("compileAndSerializeLeftmostTest('const a = 1, b = (1, 2)')", "'const a = 1, b = (1, 2)'"); |
+shouldBe("compileAndSerializeLeftmostTest('const a = (1, 2), b = (1, 2)')", "'const a = (1, 2), b = (1, 2)'"); |
+ |
+shouldBe("compileAndSerialize('(function () { new (a.b()).c })')", "'(function () { new (a.b()).c })'"); |