Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1019)

Side by Side Diff: frog/corejs.dart

Issue 9408001: Throw NoSuchMethod or IllegalArgument on bad operators or bad arguments to (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /** 5 /**
6 * Generates JS helpers for dart:core. This used to be in a file "core.js". 6 * Generates JS helpers for dart:core. This used to be in a file "core.js".
7 * Having them in Dart code means we can easily control which are generated. 7 * Having them in Dart code means we can easily control which are generated.
8 */ 8 */
9 // TODO(jmesserly): one idea to make this cleaner: put these as private "native" 9 // TODO(jmesserly): one idea to make this cleaner: put these as private "native"
10 // methods somewhere in a library that we import. This would be rather elegant 10 // methods somewhere in a library that we import. This would be rather elegant
(...skipping 26 matching lines...) Expand all
37 CoreJs(): _usedOperators = {}, writer = new CodeWriter(); 37 CoreJs(): _usedOperators = {}, writer = new CodeWriter();
38 38
39 /** 39 /**
40 * Generates the special operator method, e.g. $add. 40 * Generates the special operator method, e.g. $add.
41 * We want to do $add(x, y) instead of x.$add(y) so it doesn't box. 41 * We want to do $add(x, y) instead of x.$add(y) so it doesn't box.
42 * Same idea for the other methods. 42 * Same idea for the other methods.
43 */ 43 */
44 void useOperator(String name) { 44 void useOperator(String name) {
45 if (_usedOperators[name] != null) return; 45 if (_usedOperators[name] != null) return;
46 46
47 if (name != ':ne' && name != ':eq') {
48 // TODO(jimhug): Only do this once!
49 world.gen.markTypeUsed(world.corelib.types['NoSuchMethodException']);
kasperl 2012/02/15 11:54:49 How about adding a helper for this statement?
floitsch 2012/02/15 13:11:43 Done.
50 }
51 if (name != ':bit_not' && name != ':negate') {
52 // TODO(jimhug): Only do this once!
53 world.gen.markTypeUsed(world.corelib.types['IllegalArgumentException']);
54 }
55
47 var code; 56 var code;
48 switch (name) { 57 switch (name) {
49 case ':ne': 58 case ':ne':
50 code = _NE_FUNCTION; 59 code = _NE_FUNCTION;
51 break; 60 break;
52 61
53 case ':eq': 62 case ':eq':
54 ensureDefProp(); 63 ensureDefProp();
55 code = _EQ_FUNCTION; 64 code = _EQ_FUNCTION;
56 break; 65 break;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 if (useNotNullBool) { 147 if (useNotNullBool) {
139 useThrow = true; 148 useThrow = true;
140 w.writeln(_NOTNULL_BOOL_FUNCTION); 149 w.writeln(_NOTNULL_BOOL_FUNCTION);
141 } 150 }
142 151
143 if (useThrow) { 152 if (useThrow) {
144 w.writeln(_THROW_FUNCTION); 153 w.writeln(_THROW_FUNCTION);
145 } 154 }
146 155
147 if (useIndex) { 156 if (useIndex) {
157 world.gen.markTypeUsed(world.corelib.types['NoSuchMethodException']);
148 ensureDefProp(); 158 ensureDefProp();
149 w.writeln(options.disableBoundsChecks ? 159 w.writeln(options.disableBoundsChecks ?
150 _INDEX_OPERATORS : _CHECKED_INDEX_OPERATORS); 160 _INDEX_OPERATORS : _CHECKED_INDEX_OPERATORS);
151 } 161 }
152 162
153 if (useSetIndex) { 163 if (useSetIndex) {
164 world.gen.markTypeUsed(world.corelib.types['NoSuchMethodException']);
154 ensureDefProp(); 165 ensureDefProp();
155 w.writeln(options.disableBoundsChecks ? 166 w.writeln(options.disableBoundsChecks ?
156 _SETINDEX_OPERATORS : _CHECKED_SETINDEX_OPERATORS); 167 _SETINDEX_OPERATORS : _CHECKED_SETINDEX_OPERATORS);
157 } 168 }
158 169
159 if (useIsolates) { 170 if (useIsolates) {
160 if (useWrap0) { 171 if (useWrap0) {
161 w.writeln(_WRAP_CALL0_FUNCTION); 172 w.writeln(_WRAP_CALL0_FUNCTION);
162 } 173 }
163 if (useWrap1) { 174 if (useWrap1) {
(...skipping 24 matching lines...) Expand all
188 'Object.prototype.\$typeNameOf);'); 199 'Object.prototype.\$typeNameOf);');
189 } 200 }
190 } 201 }
191 } 202 }
192 203
193 204
194 /** Snippet for `$ne`. */ 205 /** Snippet for `$ne`. */
195 final String _NE_FUNCTION = @""" 206 final String _NE_FUNCTION = @"""
196 function $ne(x, y) { 207 function $ne(x, y) {
197 if (x == null) return y != null; 208 if (x == null) return y != null;
198 return (typeof(x) == 'number' && typeof(y) == 'number') || 209 return (typeof(x) != 'object') ? x !== y : !x.$eq(y);
kasperl 2012/02/15 11:54:49 This changes things for functions, right? I guess
floitsch 2012/02/15 13:11:43 AFAICS functions don't override the $eq method and
199 (typeof(x) == 'boolean' && typeof(y) == 'boolean') ||
200 (typeof(x) == 'string' && typeof(y) == 'string')
201 ? x != y : !x.$eq(y);
202 }"""; 210 }""";
203 211
204 /** Snippet for `$eq`. */ 212 /** Snippet for `$eq`. */
205 final String _EQ_FUNCTION = @""" 213 final String _EQ_FUNCTION = @"""
206 function $eq(x, y) { 214 function $eq(x, y) {
207 if (x == null) return y == null; 215 if (x == null) return y == null;
208 return (typeof(x) == 'number' && typeof(y) == 'number') || 216 return (typeof(x) != 'object') ? x === y : x.$eq(y);
209 (typeof(x) == 'boolean' && typeof(y) == 'boolean') ||
210 (typeof(x) == 'string' && typeof(y) == 'string')
211 ? x == y : x.$eq(y);
212 } 217 }
213 // TODO(jimhug): Should this or should it not match equals? 218 // TODO(jimhug): Should this or should it not match equals?
214 $defProp(Object.prototype, '$eq', function(other) { 219 $defProp(Object.prototype, '$eq', function(other) {
215 return this === other; 220 return this === other;
216 });"""; 221 });""";
217 222
218 /** Snippet for `$bit_not`. */ 223 /** Snippet for `$bit_not`. */
219 final String _BIT_NOT_FUNCTION = @""" 224 final String _BIT_NOT_FUNCTION = @"""
220 function $bit_not(x) { 225 function $bit_not(x) {
221 return (typeof(x) == 'number') ? ~x : x.$bit_not(); 226 if (typeof(x) == 'number') return ~x;
227 if (typeof(x) == 'object') return x.$bit_not();
228 $throw(new NoSuchMethodException(x, "operator ~", []));
222 }"""; 229 }""";
223 230
224 /** Snippet for `$negate`. */ 231 /** Snippet for `$negate`. */
225 final String _NEGATE_FUNCTION = @""" 232 final String _NEGATE_FUNCTION = @"""
226 function $negate(x) { 233 function $negate(x) {
227 return (typeof(x) == 'number') ? -x : x.$negate(); 234 if (typeof(x) == 'number') return -x;
235 if (typeof(x) == 'object') return x.$negate();
236 $throw(new NoSuchMethodException(x, "operator negate", []));
228 }"""; 237 }""";
229 238
230 /** Snippet for `$add`. This relies on JS's string "+" to match Dart's. */ 239 /** Snippet for `$add`. This relies on JS's string "+" to match Dart's. */
231 final String _ADD_FUNCTION = @""" 240 final String _ADD_FUNCTION = @"""
232 function $add(x, y) { 241 function $add(x, y) {
233 return ((typeof(x) == 'number' && typeof(y) == 'number') || 242 if (typeof(x) == 'number') {
kasperl 2012/02/15 11:54:49 It's hard to understand what this does for perform
floitsch 2012/02/15 13:11:43 Done.
234 (typeof(x) == 'string')) 243 if (typeof(y) == 'number') return x + y;
235 ? x + y : x.$add(y); 244 $throw(new IllegalArgumentException(y));
245 } else if (typeof(x) == 'string') {
246 var str = (y == null) ? 'null' : y.toString();
247 if (typeof(str) != 'string') {
248 throw new Error("calling toString() on right hand operand of operator " +
249 "+ did not return a String");
250 }
251 return x + str;
252 } else if (typeof(x) == 'object') {
253 return x.$add(y);
254 } else {
255 $throw(new NoSuchMethodException(x, "operator +", [y]));
256 }
236 }"""; 257 }""";
237 258
238 /** Snippet for `$truncdiv`. This uses `$throw`. */ 259 /** Snippet for `$truncdiv`. This uses `$throw`. */
239 final String _TRUNCDIV_FUNCTION = @""" 260 final String _TRUNCDIV_FUNCTION = @"""
240 function $truncdiv(x, y) { 261 function $truncdiv(x, y) {
241 if (typeof(x) == 'number' && typeof(y) == 'number') { 262 if (typeof(x) == 'number') {
242 if (y == 0) $throw(new IntegerDivisionByZeroException()); 263 if (typeof(y) == 'number') {
kasperl 2012/02/15 11:54:49 if ( -> if (
floitsch 2012/02/15 13:11:43 Done.
243 var tmp = x / y; 264 if (y == 0) $throw(new IntegerDivisionByZeroException());
244 return (tmp < 0) ? Math.ceil(tmp) : Math.floor(tmp); 265 var tmp = x / y;
266 return (tmp < 0) ? Math.ceil(tmp) : Math.floor(tmp);
267 } else {
268 $throw(new IllegalArgumentException(y));
269 }
270 } else if (typeof(x) == 'object') {
271 return x.$truncdiv(y);
245 } else { 272 } else {
246 return x.$truncdiv(y); 273 $throw(new NoSuchMethodException(x, "operator ~/", [y]));
247 } 274 }
248 }"""; 275 }""";
249 276
250 /** Snippet for `$mod`. */ 277 /** Snippet for `$mod`. */
251 final String _MOD_FUNCTION = @""" 278 final String _MOD_FUNCTION = @"""
252 function $mod(x, y) { 279 function $mod(x, y) {
253 if (typeof(x) == 'number' && typeof(y) == 'number') { 280 if (typeof(x) == 'number') {
254 var result = x % y; 281 if (typeof(y) == 'number') {
255 if (result == 0) { 282 var result = x % y;
256 return 0; // Make sure we don't return -0.0. 283 if (result == 0) {
257 } else if (result < 0) { 284 return 0; // Make sure we don't return -0.0.
258 if (y < 0) { 285 } else if (result < 0) {
259 return result - y; 286 if (y < 0) {
260 } else { 287 return result - y;
261 return result + y; 288 } else {
289 return result + y;
290 }
262 } 291 }
292 return result;
293 } else {
294 $throw(new IllegalArgumentException(y));
263 } 295 }
264 return result; 296 } else if (typeof(x) == 'object') {
297 return x.$mod(y);
265 } else { 298 } else {
266 return x.$mod(y); 299 $throw(new NoSuchMethodException(x, "operator %", [y]));
267 } 300 }h
268 }"""; 301 }""";
269 302
270 /** Code snippet for all other operators. */ 303 /** Code snippet for all other operators. */
271 String _otherOperator(String jsname, String op) { 304 String _otherOperator(String jsname, String op) {
272 return """ 305 return """
273 function $jsname(x, y) { 306 function $jsname(x, y) {
274 return (typeof(x) == 'number' && typeof(y) == 'number') 307 if (typeof(x) == 'number') {
275 ? x $op y : x.$jsname(y); 308 if (typeof(y) == 'number') {
309 return x $op y;
310 } else {
311 \$throw(new IllegalArgumentException(y));
312 }
313 } else if (typeof(x) == 'object') {
314 return x.$jsname(y);
315 } else {
316 \$throw(new NoSuchMethodException(x, "operator $op", [y]));
317 }
276 }"""; 318 }""";
277 } 319 }
278 320
279 /** 321 /**
280 * Snippet for `$dynamic`. Usage: 322 * Snippet for `$dynamic`. Usage:
281 * $dynamic(name).SomeTypeName = ... method ...; 323 * $dynamic(name).SomeTypeName = ... method ...;
282 * $dynamic(name).Object = ... noSuchMethod ...; 324 * $dynamic(name).Object = ... noSuchMethod ...;
283 */ 325 */
284 final String _DYNAMIC_FUNCTION = @""" 326 final String _DYNAMIC_FUNCTION = @"""
285 function $dynamic(name) { 327 function $dynamic(name) {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 // to get the right errors - at least in checked mode (once we have that). 458 // to get the right errors - at least in checked mode (once we have that).
417 // TODO(jmesserly): do perf analysis, figure out if this is worth it and 459 // TODO(jmesserly): do perf analysis, figure out if this is worth it and
418 // what the cost of $index $setindex is on all browsers 460 // what the cost of $index $setindex is on all browsers
419 461
420 // Performance of Object.prototype methods can go down because there are 462 // Performance of Object.prototype methods can go down because there are
421 // so many of them. Instead, first time we hit it, put it on the derived 463 // so many of them. Instead, first time we hit it, put it on the derived
422 // prototype. TODO(jmesserly): make this go away by handling index more 464 // prototype. TODO(jmesserly): make this go away by handling index more
423 // like a normal method. 465 // like a normal method.
424 final String _INDEX_OPERATORS = @""" 466 final String _INDEX_OPERATORS = @"""
425 $defProp(Object.prototype, '$index', function(i) { 467 $defProp(Object.prototype, '$index', function(i) {
426 var proto = Object.getPrototypeOf(this); 468 $throw(new NoSuchMethodException(this, "operator []", [i]));
427 if (proto !== Object) {
428 proto.$index = function(i) { return this[i]; }
429 }
430 return this[i];
431 }); 469 });
432 $defProp(Array.prototype, '$index', function(i) { 470 $defProp(Array.prototype, '$index', function(i) {
433 return this[i]; 471 return this[i];
434 }); 472 });
435 $defProp(String.prototype, '$index', function(i) { 473 $defProp(String.prototype, '$index', function(i) {
436 return this[i]; 474 return this[i];
437 });"""; 475 });""";
438 476
439 final String _CHECKED_INDEX_OPERATORS = @""" 477 final String _CHECKED_INDEX_OPERATORS = @"""
440 $defProp(Object.prototype, '$index', function(i) { 478 $defProp(Object.prototype, '$index', function(i) {
441 var proto = Object.getPrototypeOf(this); 479 $throw(new NoSuchMethodException(this, "operator []", [i]));
442 if (proto !== Object) {
443 proto.$index = function(i) { return this[i]; }
444 }
445 return this[i];
446 }); 480 });
447 $defProp(Array.prototype, '$index', function(index) { 481 $defProp(Array.prototype, '$index', function(index) {
448 var i = index | 0; 482 var i = index | 0;
449 if (i !== index) { 483 if (i !== index) {
450 throw new IllegalArgumentException('index is not int'); 484 throw new IllegalArgumentException('index is not int');
451 } else if (i < 0 || i >= this.length) { 485 } else if (i < 0 || i >= this.length) {
452 throw new IndexOutOfRangeException(index); 486 throw new IndexOutOfRangeException(index);
453 } 487 }
454 return this[i]; 488 return this[i];
455 }); 489 });
456 $defProp(String.prototype, '$index', function(i) { 490 $defProp(String.prototype, '$index', function(i) {
457 return this[i]; 491 return this[i];
458 });"""; 492 });""";
459 493
460 494
461 495
462 /** Snippet for `$setindex` in Object, Array, and String. */ 496 /** Snippet for `$setindex` in Object, Array, and String. */
463 final String _SETINDEX_OPERATORS = @""" 497 final String _SETINDEX_OPERATORS = @"""
464 $defProp(Object.prototype, '$setindex', function(i, value) { 498 $defProp(Object.prototype, '$setindex', function(i, value) {
465 var proto = Object.getPrototypeOf(this); 499 $throw(new NoSuchMethodException(this, "operator []=", [i, value]));
466 if (proto !== Object) {
467 proto.$setindex = function(i, value) { return this[i] = value; }
468 }
469 return this[i] = value;
470 }); 500 });
471 $defProp(Array.prototype, '$setindex', 501 $defProp(Array.prototype, '$setindex',
472 function(i, value) { return this[i] = value; });"""; 502 function(i, value) { return this[i] = value; });""";
473 503
474 final String _CHECKED_SETINDEX_OPERATORS = @""" 504 final String _CHECKED_SETINDEX_OPERATORS = @"""
475 $defProp(Object.prototype, '$setindex', function(i, value) { 505 $defProp(Object.prototype, '$setindex', function(i, value) {
476 var proto = Object.getPrototypeOf(this); 506 $throw(new NoSuchMethodException(this, "operator []=", [i, value]));
477 if (proto !== Object) {
478 proto.$setindex = function(i, value) { return this[i] = value; }
479 }
480 return this[i] = value;
481 }); 507 });
482 $defProp(Array.prototype, '$setindex', function(index, value) { 508 $defProp(Array.prototype, '$setindex', function(index, value) {
483 var i = index | 0; 509 var i = index | 0;
484 if (i !== index) { 510 if (i !== index) {
485 throw new IllegalArgumentException('index is not int'); 511 throw new IllegalArgumentException('index is not int');
486 } else if (i < 0 || i >= this.length) { 512 } else if (i < 0 || i >= this.length) {
487 throw new IndexOutOfRangeException(index); 513 throw new IndexOutOfRangeException(index);
488 } 514 }
489 return this[i] = value; 515 return this[i] = value;
490 });"""; 516 });""";
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 551
526 /** Snippet for `$wrap_call$1`, in case it was not necessary. */ 552 /** Snippet for `$wrap_call$1`, in case it was not necessary. */
527 final String _EMPTY_WRAP_CALL1_FUNCTION = 553 final String _EMPTY_WRAP_CALL1_FUNCTION =
528 @"function $wrap_call$1(fn) { return fn; }"; 554 @"function $wrap_call$1(fn) { return fn; }";
529 555
530 /** Snippet that initializes the isolates state. */ 556 /** Snippet that initializes the isolates state. */
531 final String _ISOLATE_INIT_CODE = @""" 557 final String _ISOLATE_INIT_CODE = @"""
532 var $globalThis = this; 558 var $globalThis = this;
533 var $globals = null; 559 var $globals = null;
534 var $globalState = null;"""; 560 var $globalState = null;""";
OLDNEW
« no previous file with comments | « no previous file | tests/language/language-leg.status » ('j') | tests/language/src/StringConcatTest.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698