Pow.js (3557B)
1 // |reftest| skip-if(!xulRuntime.shell) 2 /* 3 * Any copyright is dedicated to the Public Domain. 4 * http://creativecommons.org/licenses/publicdomain/ 5 */ 6 7 var BUGNUMBER = 1135708; 8 var summary = "Implement the exponentiation operator"; 9 10 print(BUGNUMBER + ": " + summary); 11 12 // Constant folding 13 assertEq(2 ** 2 ** 3, 256); 14 assertEq(1 ** 1 ** 4, 1); 15 16 // No folding 17 var two = 2; 18 var three = 3; 19 var four = 4; 20 assertEq(two ** two ** three, 256); 21 assertEq(1 ** 1 ** four, 1); 22 23 // Operator precedence 24 assertEq(2 ** 3 / 2 ** 3, 1); 25 assertEq(2 ** 3 * 2 ** 3, 64); 26 assertEq(2 ** 3 + 2 ** 3, 16); 27 28 // With parentheses 29 assertEq((2 ** 3) ** 2, 64); 30 assertEq(2 ** (3 ** 2), 512); 31 32 // Assignment operator 33 var x = 2; 34 assertEq(x **= 2 ** 3, 256); 35 assertEq(x, 256); 36 37 // Loop to test baseline and ION 38 for (var i=0; i<10000; i++) { 39 assertEq((2 ** 3) ** 2, 64); 40 assertEq(2 ** (3 ** 2), 512); 41 var x = 2; 42 assertEq(x **= 2 ** 3, 256); 43 assertEq(x, 256); 44 } 45 46 // Comments should not be confused with exp operator 47 var a, c, e; 48 a = c = e = 2; 49 assertEq(a**/**b**/c/**/**/**d**/e, 16); 50 51 // Two stars separated should not parse as exp operator 52 assertThrowsInstanceOf(function() { return Reflect.parse("2 * * 3"); }, SyntaxError); 53 54 // Left-hand side expression must not be a unary expression. 55 for (let unaryOp of ["delete", "typeof", "void", "+", "-", "!", "~"]) { 56 assertThrowsInstanceOf(() => eval(unaryOp + " a ** 2"), SyntaxError); 57 assertThrowsInstanceOf(() => eval(unaryOp + " " + unaryOp + " a ** 2"), SyntaxError); 58 } 59 60 // Test the other |delete| operators (DELETENAME and DELETEEXPR are already tested above). 61 assertThrowsInstanceOf(() => eval("delete a.name ** 2"), SyntaxError); 62 assertThrowsInstanceOf(() => eval("delete a[0] ** 2"), SyntaxError); 63 64 // Unary expression lhs is valid if parenthesized. 65 for (let unaryOp of ["delete", "void", "+", "-", "!", "~"]) { 66 let a = 0; 67 eval("(" + unaryOp + " a) ** 2"); 68 eval("(" + unaryOp + " " + unaryOp + " a) ** 2"); 69 } 70 { 71 let a = {}; 72 (delete a.name) ** 2; 73 (delete a[0]) ** 2; 74 } 75 76 // Check if error propagation works 77 var thrower = { 78 get value() { 79 throw new Error(); 80 } 81 }; 82 83 assertThrowsInstanceOf(function() { return thrower.value ** 2; }, Error); 84 assertThrowsInstanceOf(function() { return 2 ** thrower.value; }, Error); 85 assertThrowsInstanceOf(function() { return 2 ** thrower.value ** 2; }, Error); 86 87 var convertibleToPrimitive = { 88 valueOf: function() { 89 throw new Error("oops"); 90 } 91 }; 92 93 assertThrowsInstanceOf(function() { return convertibleToPrimitive ** 3; }, Error); 94 assertThrowsInstanceOf(function() { return 3 ** convertibleToPrimitive; }, Error); 95 96 assertEq(NaN ** 2, NaN); 97 assertEq(2 ** NaN, NaN); 98 assertEq(2 ** "3", 8); 99 assertEq("2" ** 3, 8); 100 101 // Reflect.parse generates a correct parse tree for simplest case 102 var parseTree = Reflect.parse("a ** b"); 103 assertEq(parseTree.body[0].type, "ExpressionStatement"); 104 assertEq(parseTree.body[0].expression.operator, "**"); 105 assertEq(parseTree.body[0].expression.left.name, "a"); 106 assertEq(parseTree.body[0].expression.right.name, "b"); 107 108 // Reflect.parse generates a tree following the right-associativity rule 109 var parseTree = Reflect.parse("a ** b ** c"); 110 assertEq(parseTree.body[0].type, "ExpressionStatement"); 111 assertEq(parseTree.body[0].expression.left.name, "a"); 112 assertEq(parseTree.body[0].expression.right.operator, "**"); 113 assertEq(parseTree.body[0].expression.right.left.name, "b"); 114 assertEq(parseTree.body[0].expression.right.right.name, "c"); 115 116 if (typeof reportCompare === "function") 117 reportCompare(true, true);