| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #library('js_helper'); | 5 #library('js_helper'); |
| 6 | 6 |
| 7 #import('coreimpl.dart'); | 7 #import('coreimpl.dart'); |
| 8 | 8 |
| 9 #source('date_helper.dart'); | 9 #source('date_helper.dart'); |
| 10 #source('regexp_helper.dart'); | 10 #source('regexp_helper.dart'); |
| 11 #source('string_helper.dart'); | 11 #source('string_helper.dart'); |
| 12 | 12 |
| 13 /** | 13 /** |
| 14 * Returns true if both arguments are numbers. | 14 * Returns true if both arguments are numbers. |
| 15 * If only the first argument is a number, throws the given message as | 15 * |
| 16 * exception. | 16 * If only the first argument is a number, an |
| 17 */ | 17 * [IllegalArgumentException] with the other argument is thrown. |
| 18 bool checkNumbers(var a, var b, var message) { | 18 */ |
| 19 bool checkNumbers(var a, var b) { |
| 19 if (a is num) { | 20 if (a is num) { |
| 20 if (b is num) { | 21 if (b is num) { |
| 21 return true; | 22 return true; |
| 22 } else { | 23 } else { |
| 23 checkNull(b); | 24 checkNull(b); |
| 24 throw new IllegalArgumentException(message); | 25 throw new IllegalArgumentException(b); |
| 25 } | 26 } |
| 26 } | 27 } |
| 27 return false; | 28 return false; |
| 28 } | 29 } |
| 29 | 30 |
| 30 | 31 |
| 31 bool isJsArray(var value) { | 32 bool isJsArray(var value) { |
| 32 return value !== null && JS('bool', @'$0.constructor === Array', value); | 33 return value !== null && JS('bool', @'$0.constructor === Array', value); |
| 33 } | 34 } |
| 34 | 35 |
| 35 | 36 |
| 36 add(var a, var b) { | 37 add(var a, var b) { |
| 37 if (checkNumbers(a, b, 'num+ expects a number as second operand.')) { | 38 if (checkNumbers(a, b)) { |
| 38 return JS('num', @'$0 + $1', a, b); | 39 return JS('num', @'$0 + $1', a, b); |
| 39 } else if (a is String) { | 40 } else if (a is String) { |
| 40 b = b.toString(); | 41 b = b.toString(); |
| 41 if (b is String) { | 42 if (b is String) { |
| 42 return JS('String', @'$0 + $1', a, b); | 43 return JS('String', @'$0 + $1', a, b); |
| 43 } | 44 } |
| 44 checkNull(b); | 45 checkNull(b); |
| 45 throw new IllegalArgumentException(b); | 46 throw new IllegalArgumentException(b); |
| 46 } | 47 } |
| 47 checkNull(a); | 48 checkNull(a); |
| 48 return UNINTERCEPTED(a + b); | 49 return UNINTERCEPTED(a + b); |
| 49 } | 50 } |
| 50 | 51 |
| 51 div(var a, var b) { | 52 div(var a, var b) { |
| 52 if (checkNumbers(a, b, 'num/ expects a number as second operand.')) { | 53 if (checkNumbers(a, b)) { |
| 53 return JS('num', @'$0 / $1', a, b); | 54 return JS('num', @'$0 / $1', a, b); |
| 54 } | 55 } |
| 55 checkNull(a); | 56 checkNull(a); |
| 56 return UNINTERCEPTED(a / b); | 57 return UNINTERCEPTED(a / b); |
| 57 } | 58 } |
| 58 | 59 |
| 59 mul(var a, var b) { | 60 mul(var a, var b) { |
| 60 if (checkNumbers(a, b, 'num* expects a number as second operand.')) { | 61 if (checkNumbers(a, b)) { |
| 61 return JS('num', @'$0 * $1', a, b); | 62 return JS('num', @'$0 * $1', a, b); |
| 62 } | 63 } |
| 63 checkNull(a); | 64 checkNull(a); |
| 64 return UNINTERCEPTED(a * b); | 65 return UNINTERCEPTED(a * b); |
| 65 } | 66 } |
| 66 | 67 |
| 67 sub(var a, var b) { | 68 sub(var a, var b) { |
| 68 if (checkNumbers(a, b, 'num- expects a number as second operand.')) { | 69 if (checkNumbers(a, b)) { |
| 69 return JS('num', @'$0 - $1', a, b); | 70 return JS('num', @'$0 - $1', a, b); |
| 70 } | 71 } |
| 71 checkNull(a); | 72 checkNull(a); |
| 72 return UNINTERCEPTED(a - b); | 73 return UNINTERCEPTED(a - b); |
| 73 } | 74 } |
| 74 | 75 |
| 75 mod(var a, var b) { | 76 mod(var a, var b) { |
| 76 if (checkNumbers(a, b, 'int% expects an int as second operand.')) { | 77 if (checkNumbers(a, b)) { |
| 77 if (b === 0) throw new IntegerDivisionByZeroException(); | |
| 78 // Euclidean Modulo. | 78 // Euclidean Modulo. |
| 79 int result = JS('num', @'$0 % $1', a, b); | 79 int result = JS('num', @'$0 % $1', a, b); |
| 80 if (result == 0) return 0; // Make sure we don't return -0.0. | 80 if (result == 0) return 0; // Make sure we don't return -0.0. |
| 81 if (result > 0) return result; | 81 if (result > 0) return result; |
| 82 if (b < 0) { | 82 if (b < 0) { |
| 83 return result - b; | 83 return result - b; |
| 84 } else { | 84 } else { |
| 85 return result + b; | 85 return result + b; |
| 86 } | 86 } |
| 87 } | 87 } |
| 88 checkNull(a); | 88 checkNull(a); |
| 89 return UNINTERCEPTED(a % b); | 89 return UNINTERCEPTED(a % b); |
| 90 } | 90 } |
| 91 | 91 |
| 92 tdiv(var a, var b) { | 92 tdiv(var a, var b) { |
| 93 if (checkNumbers(a, b, 'num~/ expects a number as second operand.')) { | 93 if (checkNumbers(a, b)) { |
| 94 if (b === 0) throw new IntegerDivisionByZeroException(); | |
| 95 return (a / b).truncate(); | 94 return (a / b).truncate(); |
| 96 } | 95 } |
| 97 checkNull(a); | 96 checkNull(a); |
| 98 return UNINTERCEPTED(a ~/ b); | 97 return UNINTERCEPTED(a ~/ b); |
| 99 } | 98 } |
| 100 | 99 |
| 101 eq(var a, var b) { | 100 eq(var a, var b) { |
| 102 if (JS('bool', @'typeof $0 === "object"', a)) { | 101 if (JS('bool', @'typeof $0 === "object"', a)) { |
| 103 if (JS_HAS_EQUALS(a)) { | 102 if (JS_HAS_EQUALS(a)) { |
| 104 return UNINTERCEPTED(a == b) === true; | 103 return UNINTERCEPTED(a == b) === true; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 120 return UNINTERCEPTED(a == null) === true; | 119 return UNINTERCEPTED(a == null) === true; |
| 121 } else { | 120 } else { |
| 122 return false; | 121 return false; |
| 123 } | 122 } |
| 124 } else { | 123 } else { |
| 125 return JS('bool', @'typeof $0 === "undefined"', a); | 124 return JS('bool', @'typeof $0 === "undefined"', a); |
| 126 } | 125 } |
| 127 } | 126 } |
| 128 | 127 |
| 129 gt(var a, var b) { | 128 gt(var a, var b) { |
| 130 if (checkNumbers(a, b, 'num> expects a number as second operand.')) { | 129 if (checkNumbers(a, b)) { |
| 131 return JS('bool', @'$0 > $1', a, b); | 130 return JS('bool', @'$0 > $1', a, b); |
| 132 } | 131 } |
| 133 checkNull(a); | 132 checkNull(a); |
| 134 return UNINTERCEPTED(a > b); | 133 return UNINTERCEPTED(a > b); |
| 135 } | 134 } |
| 136 | 135 |
| 137 ge(var a, var b) { | 136 ge(var a, var b) { |
| 138 if (checkNumbers(a, b, 'num>= expects a number as second operand.')) { | 137 if (checkNumbers(a, b)) { |
| 139 return JS('bool', @'$0 >= $1', a, b); | 138 return JS('bool', @'$0 >= $1', a, b); |
| 140 } | 139 } |
| 141 checkNull(a); | 140 checkNull(a); |
| 142 return UNINTERCEPTED(a >= b); | 141 return UNINTERCEPTED(a >= b); |
| 143 } | 142 } |
| 144 | 143 |
| 145 lt(var a, var b) { | 144 lt(var a, var b) { |
| 146 if (checkNumbers(a, b, 'num< expects a number as second operand.')) { | 145 if (checkNumbers(a, b)) { |
| 147 return JS('bool', @'$0 < $1', a, b); | 146 return JS('bool', @'$0 < $1', a, b); |
| 148 } | 147 } |
| 149 checkNull(a); | 148 checkNull(a); |
| 150 return UNINTERCEPTED(a < b); | 149 return UNINTERCEPTED(a < b); |
| 151 } | 150 } |
| 152 | 151 |
| 153 le(var a, var b) { | 152 le(var a, var b) { |
| 154 if (checkNumbers(a, b, 'num<= expects a number as second operand.')) { | 153 if (checkNumbers(a, b)) { |
| 155 return JS('bool', @'$0 <= $1', a, b); | 154 return JS('bool', @'$0 <= $1', a, b); |
| 156 } | 155 } |
| 157 checkNull(a); | 156 checkNull(a); |
| 158 return UNINTERCEPTED(a <= b); | 157 return UNINTERCEPTED(a <= b); |
| 159 } | 158 } |
| 160 | 159 |
| 161 shl(var a, var b) { | 160 shl(var a, var b) { |
| 162 // TODO(floitsch): inputs must be integers. | 161 // TODO(floitsch): inputs must be integers. |
| 163 if (checkNumbers(a, b, 'int<< expects an int as second operand.')) { | 162 if (checkNumbers(a, b)) { |
| 164 if (b < 0) throw new IllegalArgumentException(b); | 163 if (b < 0) throw new IllegalArgumentException(b); |
| 165 return JS('num', @'$0 << $1', a, b); | 164 return JS('num', @'$0 << $1', a, b); |
| 166 } | 165 } |
| 167 checkNull(a); | 166 checkNull(a); |
| 168 return UNINTERCEPTED(a << b); | 167 return UNINTERCEPTED(a << b); |
| 169 } | 168 } |
| 170 | 169 |
| 171 shr(var a, var b) { | 170 shr(var a, var b) { |
| 172 // TODO(floitsch): inputs must be integers. | 171 // TODO(floitsch): inputs must be integers. |
| 173 if (checkNumbers(a, b, 'int>> expects an int as second operand.')) { | 172 if (checkNumbers(a, b)) { |
| 174 if (b < 0) throw new IllegalArgumentException(b); | 173 if (b < 0) throw new IllegalArgumentException(b); |
| 175 return JS('num', @'$0 >> $1', a, b); | 174 return JS('num', @'$0 >> $1', a, b); |
| 176 } | 175 } |
| 177 checkNull(a); | 176 checkNull(a); |
| 178 return UNINTERCEPTED(a >> b); | 177 return UNINTERCEPTED(a >> b); |
| 179 } | 178 } |
| 180 | 179 |
| 181 and(var a, var b) { | 180 and(var a, var b) { |
| 182 // TODO(floitsch): inputs must be integers. | 181 // TODO(floitsch): inputs must be integers. |
| 183 if (checkNumbers(a, b, 'int& expects an int as second operand.')) { | 182 if (checkNumbers(a, b)) { |
| 184 return JS('num', @'$0 & $1', a, b); | 183 return JS('num', @'$0 & $1', a, b); |
| 185 } | 184 } |
| 186 checkNull(a); | 185 checkNull(a); |
| 187 return UNINTERCEPTED(a & b); | 186 return UNINTERCEPTED(a & b); |
| 188 } | 187 } |
| 189 | 188 |
| 190 or(var a, var b) { | 189 or(var a, var b) { |
| 191 // TODO(floitsch): inputs must be integers. | 190 // TODO(floitsch): inputs must be integers. |
| 192 if (checkNumbers(a, b, 'int| expects an int as second operand.')) { | 191 if (checkNumbers(a, b)) { |
| 193 return JS('num', @'$0 | $1', a, b); | 192 return JS('num', @'$0 | $1', a, b); |
| 194 } | 193 } |
| 195 checkNull(a); | 194 checkNull(a); |
| 196 return UNINTERCEPTED(a | b); | 195 return UNINTERCEPTED(a | b); |
| 197 } | 196 } |
| 198 | 197 |
| 199 xor(var a, var b) { | 198 xor(var a, var b) { |
| 200 // TODO(floitsch): inputs must be integers. | 199 // TODO(floitsch): inputs must be integers. |
| 201 if (checkNumbers(a, b, 'int^ expects an int as second operand.')) { | 200 if (checkNumbers(a, b)) { |
| 202 return JS('num', @'$0 ^ $1', a, b); | 201 return JS('num', @'$0 ^ $1', a, b); |
| 203 } | 202 } |
| 204 checkNull(a); | 203 checkNull(a); |
| 205 return UNINTERCEPTED(a ^ b); | 204 return UNINTERCEPTED(a ^ b); |
| 206 } | 205 } |
| 207 | 206 |
| 208 not(var a) { | 207 not(var a) { |
| 209 if (JS('bool', @'typeof $0 === "number"', a)) return JS('num', @'~$0', a); | 208 if (JS('bool', @'typeof $0 === "number"', a)) return JS('num', @'~$0', a); |
| 210 checkNull(a); | 209 checkNull(a); |
| 211 return UNINTERCEPTED(~a); | 210 return UNINTERCEPTED(~a); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 checkNull(str); | 516 checkNull(str); |
| 518 if (str is !String) throw new IllegalArgumentException(str); | 517 if (str is !String) throw new IllegalArgumentException(str); |
| 519 var value = JS('num', @'Date.parse($0)', str); | 518 var value = JS('num', @'Date.parse($0)', str); |
| 520 if (value.isNaN()) throw new IllegalArgumentException(str); | 519 if (value.isNaN()) throw new IllegalArgumentException(str); |
| 521 return value; | 520 return value; |
| 522 } | 521 } |
| 523 } | 522 } |
| 524 | 523 |
| 525 builtin$compareTo$1(a, b) { | 524 builtin$compareTo$1(a, b) { |
| 526 checkNull(a); | 525 checkNull(a); |
| 527 if (checkNumbers(a, b, 'illegal argument')) { | 526 if (checkNumbers(a, b)) { |
| 528 if (a < b) { | 527 if (a < b) { |
| 529 return -1; | 528 return -1; |
| 530 } else if (a > b) { | 529 } else if (a > b) { |
| 531 return 1; | 530 return 1; |
| 532 } else if (a == b) { | 531 } else if (a == b) { |
| 533 if (a == 0) { | 532 if (a == 0) { |
| 534 bool aIsNegative = a.isNegative(); | 533 bool aIsNegative = a.isNegative(); |
| 535 bool bIsNegative = b.isNegative(); | 534 bool bIsNegative = b.isNegative(); |
| 536 if (aIsNegative == bIsNegative) return 0; | 535 if (aIsNegative == bIsNegative) return 0; |
| 537 if (aIsNegative) return -1; | 536 if (aIsNegative) return -1; |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 checkNull(receiver); | 861 checkNull(receiver); |
| 863 if (receiver is num) { | 862 if (receiver is num) { |
| 864 return JS('bool', @'isNaN($0)', receiver); | 863 return JS('bool', @'isNaN($0)', receiver); |
| 865 } else { | 864 } else { |
| 866 return UNINTERCEPTED(receiver.isNegative()); | 865 return UNINTERCEPTED(receiver.isNegative()); |
| 867 } | 866 } |
| 868 } | 867 } |
| 869 | 868 |
| 870 builtin$remainder$1(a, b) { | 869 builtin$remainder$1(a, b) { |
| 871 checkNull(a); | 870 checkNull(a); |
| 872 if (checkNumbers(a, b, 'num.remainder expects a number as second operand.')) { | 871 if (checkNumbers(a, b)) { |
| 873 if (b === 0) throw new IntegerDivisionByZeroException(); | |
| 874 return JS('num', @'$0 % $1', a, b); | 872 return JS('num', @'$0 % $1', a, b); |
| 875 } else { | 873 } else { |
| 876 return UNINTERCEPTED(a.remainder(b)); | 874 return UNINTERCEPTED(a.remainder(b)); |
| 877 } | 875 } |
| 878 } | 876 } |
| 879 | 877 |
| 880 builtin$abs$0(receiver) { | 878 builtin$abs$0(receiver) { |
| 881 checkNull(receiver); | 879 checkNull(receiver); |
| 882 if (receiver is !num) return UNINTERCEPTED(receiver.abs()); | 880 if (receiver is !num) return UNINTERCEPTED(receiver.abs()); |
| 883 | 881 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 checkNull(receiver); | 920 checkNull(receiver); |
| 923 if (receiver is !num) return UNINTERCEPTED(receiver.negate()); | 921 if (receiver is !num) return UNINTERCEPTED(receiver.negate()); |
| 924 | 922 |
| 925 return JS('num', @'-$0', receiver); | 923 return JS('num', @'-$0', receiver); |
| 926 } | 924 } |
| 927 | 925 |
| 928 builtin$round$0(receiver) { | 926 builtin$round$0(receiver) { |
| 929 checkNull(receiver); | 927 checkNull(receiver); |
| 930 if (receiver is !num) return UNINTERCEPTED(receiver.round()); | 928 if (receiver is !num) return UNINTERCEPTED(receiver.round()); |
| 931 | 929 |
| 932 return JS('num', @'Math.round($0)', receiver); | 930 if (JS('bool', @'$0 < 0', receiver)) { |
| 931 return JS('num', @'-Math.round(-$0)', receiver); |
| 932 } else { |
| 933 return JS('num', @'Math.round($0)', receiver); |
| 934 } |
| 933 } | 935 } |
| 934 | 936 |
| 935 builtin$toDouble$0(receiver) { | 937 builtin$toDouble$0(receiver) { |
| 936 checkNull(receiver); | 938 checkNull(receiver); |
| 937 if (receiver is !num) return UNINTERCEPTED(receiver.toDouble()); | 939 if (receiver is !num) return UNINTERCEPTED(receiver.toDouble()); |
| 938 | 940 |
| 939 // TODO(ahe): Just return receiver? | 941 // TODO(ahe): Just return receiver? |
| 940 return JS('double', @'$0 + 0', receiver); | 942 return JS('double', @'$0 + 0', receiver); |
| 941 } | 943 } |
| 942 | 944 |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 } | 1289 } |
| 1288 } | 1290 } |
| 1289 } else if (JS('bool', @'$0 instanceof RangeError', ex)) { | 1291 } else if (JS('bool', @'$0 instanceof RangeError', ex)) { |
| 1290 var message = JS('String', @'$0.message', ex); | 1292 var message = JS('String', @'$0.message', ex); |
| 1291 if (message.contains('call stack')) { | 1293 if (message.contains('call stack')) { |
| 1292 return new StackOverflowException(); | 1294 return new StackOverflowException(); |
| 1293 } | 1295 } |
| 1294 } | 1296 } |
| 1295 return ex; | 1297 return ex; |
| 1296 } | 1298 } |
| OLD | NEW |