| 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('dart:_js_helper'); | 5 #library('dart:_js_helper'); |
| 6 | 6 |
| 7 #import('dart:coreimpl'); | 7 #import('dart:coreimpl'); |
| 8 #import('dart:collection'); | 8 #import('dart:collection'); |
| 9 | 9 |
| 10 #source('constant_map.dart'); | 10 #source('constant_map.dart'); |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 ListIterator(List<T> this.list) : i = 0; | 346 ListIterator(List<T> this.list) : i = 0; |
| 347 bool get hasNext => i < JS('int', r'#.length', list); | 347 bool get hasNext => i < JS('int', r'#.length', list); |
| 348 T next() { | 348 T next() { |
| 349 if (!hasNext) throw new StateError("No more elements"); | 349 if (!hasNext) throw new StateError("No more elements"); |
| 350 var value = JS('Object', r'#[#]', list, i); | 350 var value = JS('Object', r'#[#]', list, i); |
| 351 i += 1; | 351 i += 1; |
| 352 return value; | 352 return value; |
| 353 } | 353 } |
| 354 } | 354 } |
| 355 | 355 |
| 356 createInvocationMirror(name, internalName, type, arguments, argumentNames) => | |
| 357 new JSInvocationMirror(name, internalName, type, arguments, argumentNames); | |
| 358 | |
| 359 class JSInvocationMirror implements InvocationMirror { | |
| 360 static const METHOD = 0; | |
| 361 static const GETTER = 1; | |
| 362 static const SETTER = 2; | |
| 363 | |
| 364 final String memberName; | |
| 365 final String _internalName; | |
| 366 final int _kind; | |
| 367 final List _arguments; | |
| 368 final List _namedArgumentNames; | |
| 369 /** Map from argument name to index in _arguments. */ | |
| 370 Map<String,dynamic> _namedIndices = null; | |
| 371 | |
| 372 JSInvocationMirror(this.memberName, | |
| 373 this._internalName, | |
| 374 this._kind, | |
| 375 this._arguments, | |
| 376 this._namedArgumentNames); | |
| 377 | |
| 378 bool get isMethod => _kind == METHOD; | |
| 379 bool get isGetter => _kind == GETTER; | |
| 380 bool get isSetter => _kind == SETTER; | |
| 381 bool get isAccessor => _kind != METHOD; | |
| 382 | |
| 383 List get positionalArguments { | |
| 384 if (isGetter) return null; | |
| 385 var list = []; | |
| 386 var argumentCount = | |
| 387 _arguments.length - _namedArgumentNames.length; | |
| 388 for (var index = 0 ; index < argumentCount ; index++) { | |
| 389 list.add(_arguments[index]); | |
| 390 } | |
| 391 return list; | |
| 392 } | |
| 393 | |
| 394 Map<String,dynamic> get namedArguments { | |
| 395 if (isAccessor) return null; | |
| 396 var map = <String,dynamic>{}; | |
| 397 int namedArgumentCount = _namedArgumentNames.length; | |
| 398 int namedArgumentsStartIndex = _arguments.length - namedArgumentCount; | |
| 399 for (int i = 0; i < namedArgumentCount; i++) { | |
| 400 map[_namedArgumentNames[i]] = _arguments[namedArgumentsStartIndex + i]; | |
| 401 } | |
| 402 return map; | |
| 403 } | |
| 404 | |
| 405 invokeOn(Object object) { | |
| 406 List arguments = _arguments; | |
| 407 if (!isJsArray(arguments)) arguments = new List.from(arguments); | |
| 408 return JS("var", "#[#].apply(#, #)", | |
| 409 object, _internalName, object, arguments); | |
| 410 } | |
| 411 } | |
| 412 | |
| 413 class Primitives { | 356 class Primitives { |
| 414 static int hashCodeSeed = 0; | 357 static int hashCodeSeed = 0; |
| 415 | 358 |
| 416 static int objectHashCode(object) { | 359 static int objectHashCode(object) { |
| 417 int hash = JS('var', r'#.$identityHash', object); | 360 int hash = JS('var', r'#.$identityHash', object); |
| 418 if (hash == null) { | 361 if (hash == null) { |
| 419 // TOOD(ahe): We should probably randomize this somehow. | 362 // TOOD(ahe): We should probably randomize this somehow. |
| 420 hash = ++hashCodeSeed; | 363 hash = ++hashCodeSeed; |
| 421 JS('void', r'#.$identityHash = #', object, hash); | 364 JS('void', r'#.$identityHash = #', object, hash); |
| 422 } | 365 } |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 JS('void', '#.sort()', listOfNamedArguments); | 641 JS('void', '#.sort()', listOfNamedArguments); |
| 699 listOfNamedArguments.forEach((String name) { | 642 listOfNamedArguments.forEach((String name) { |
| 700 buffer.add('\$$name'); | 643 buffer.add('\$$name'); |
| 701 arguments.add(namedArguments[name]); | 644 arguments.add(namedArguments[name]); |
| 702 }); | 645 }); |
| 703 } | 646 } |
| 704 | 647 |
| 705 String selectorName = 'call\$$argumentCount$buffer'; | 648 String selectorName = 'call\$$argumentCount$buffer'; |
| 706 var jsFunction = JS('var', '#[#]', function, selectorName); | 649 var jsFunction = JS('var', '#[#]', function, selectorName); |
| 707 if (jsFunction == null) { | 650 if (jsFunction == null) { |
| 708 throw new NoSuchMethodError(function, selectorName, arguments, {}); | 651 throw new NoSuchMethodError(function, selectorName, arguments); |
| 709 } | 652 } |
| 710 // We bound 'this' to [function] because of how we compile | 653 // We bound 'this' to [function] because of how we compile |
| 711 // closures: escaped local variables are stored and accessed through | 654 // closures: escaped local variables are stored and accessed through |
| 712 // [function]. | 655 // [function]. |
| 713 return JS('var', '#.apply(#, #)', jsFunction, function, arguments); | 656 return JS('var', '#.apply(#, #)', jsFunction, function, arguments); |
| 714 } | 657 } |
| 715 } | 658 } |
| 716 | 659 |
| 717 /** | 660 /** |
| 718 * Called by generated code to throw an illegal-argument exception, | 661 * Called by generated code to throw an illegal-argument exception, |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 // allow us to get very detailed information about what kind of | 882 // allow us to get very detailed information about what kind of |
| 940 // exception occurred. | 883 // exception occurred. |
| 941 var type = JS('var', r'#.type', ex); | 884 var type = JS('var', r'#.type', ex); |
| 942 var name = JS('var', r'#.arguments ? #.arguments[0] : ""', ex, ex); | 885 var name = JS('var', r'#.arguments ? #.arguments[0] : ""', ex, ex); |
| 943 if (type == 'property_not_function' || | 886 if (type == 'property_not_function' || |
| 944 type == 'called_non_callable' || | 887 type == 'called_non_callable' || |
| 945 type == 'non_object_property_call' || | 888 type == 'non_object_property_call' || |
| 946 type == 'non_object_property_load') { | 889 type == 'non_object_property_load') { |
| 947 return new NullPointerException(); | 890 return new NullPointerException(); |
| 948 } else if (type == 'undefined_method') { | 891 } else if (type == 'undefined_method') { |
| 949 return new NoSuchMethodError('', name, [], {}); | 892 return new NoSuchMethodError('', name, []); |
| 950 } | 893 } |
| 951 | 894 |
| 952 var ieErrorCode = JS('int', '#.number & 0xffff', ex); | 895 var ieErrorCode = JS('int', '#.number & 0xffff', ex); |
| 953 var ieFacilityNumber = JS('int', '#.number>>16 & 0x1FFF', ex); | 896 var ieFacilityNumber = JS('int', '#.number>>16 & 0x1FFF', ex); |
| 954 // If we cannot use [type] to determine what kind of exception | 897 // If we cannot use [type] to determine what kind of exception |
| 955 // we're dealing with we fall back on looking at the exception | 898 // we're dealing with we fall back on looking at the exception |
| 956 // message if it is available and a string. | 899 // message if it is available and a string. |
| 957 if (message is String) { | 900 if (message is String) { |
| 958 if (message.endsWith('is null') || | 901 if (message.endsWith('is null') || |
| 959 message.endsWith('is undefined') || | 902 message.endsWith('is undefined') || |
| 960 message.endsWith('is null or undefined')) { | 903 message.endsWith('is null or undefined')) { |
| 961 return new NullPointerException(); | 904 return new NullPointerException(); |
| 962 } else if (message.contains(' is not a function') || | 905 } else if (message.contains(' is not a function') || |
| 963 (ieErrorCode == 438 && ieFacilityNumber == 10)) { | 906 (ieErrorCode == 438 && ieFacilityNumber == 10)) { |
| 964 // Examples: | 907 // Examples: |
| 965 // x.foo is not a function | 908 // x.foo is not a function |
| 966 // 'undefined' is not a function (evaluating 'x.foo(1,2,3)') | 909 // 'undefined' is not a function (evaluating 'x.foo(1,2,3)') |
| 967 // Object doesn't support property or method 'foo' which sets the error | 910 // Object doesn't support property or method 'foo' which sets the error |
| 968 // code 438 in IE. | 911 // code 438 in IE. |
| 969 // TODO(kasperl): Compute the right name if possible. | 912 // TODO(kasperl): Compute the right name if possible. |
| 970 return new NoSuchMethodError('', '<unknown>', [], {}); | 913 return new NoSuchMethodError('', '<unknown>', []); |
| 971 } | 914 } |
| 972 } | 915 } |
| 973 | 916 |
| 974 // If we cannot determine what kind of error this is, we fall back | 917 // If we cannot determine what kind of error this is, we fall back |
| 975 // to reporting this as a generic exception. It's probably better | 918 // to reporting this as a generic exception. It's probably better |
| 976 // than nothing. | 919 // than nothing. |
| 977 return new Exception(message is String ? message : ''); | 920 return new Exception(message is String ? message : ''); |
| 978 } | 921 } |
| 979 | 922 |
| 980 if (JS('bool', r'# instanceof RangeError', ex)) { | 923 if (JS('bool', r'# instanceof RangeError', ex)) { |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 // Compare to true to avoid boolean conversion check in checked | 1370 // Compare to true to avoid boolean conversion check in checked |
| 1428 // mode. | 1371 // mode. |
| 1429 if (!identical(condition, true)) throw new AssertionError(); | 1372 if (!identical(condition, true)) throw new AssertionError(); |
| 1430 } | 1373 } |
| 1431 | 1374 |
| 1432 /** | 1375 /** |
| 1433 * Called by generated code when a method that must be statically | 1376 * Called by generated code when a method that must be statically |
| 1434 * resolved cannot be found. | 1377 * resolved cannot be found. |
| 1435 */ | 1378 */ |
| 1436 void throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) { | 1379 void throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) { |
| 1437 throw new NoSuchMethodError(obj, name, arguments, const {}, | 1380 throw new NoSuchMethodError(obj, name, arguments, expectedArgumentNames); |
| 1438 expectedArgumentNames); | |
| 1439 } | 1381 } |
| 1440 | 1382 |
| 1441 /** | 1383 /** |
| 1442 * Called by generated code when a static field's initializer references the | 1384 * Called by generated code when a static field's initializer references the |
| 1443 * field that is currently being initialized. | 1385 * field that is currently being initialized. |
| 1444 */ | 1386 */ |
| 1445 void throwCyclicInit(String staticName) { | 1387 void throwCyclicInit(String staticName) { |
| 1446 throw new RuntimeError("Cyclic initialization for static $staticName"); | 1388 throw new RuntimeError("Cyclic initialization for static $staticName"); |
| 1447 } | 1389 } |
| 1448 | 1390 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1460 JS('void', r'#.runtimeTypeCache[#] = #', JS_CURRENT_ISOLATE(), key, | 1402 JS('void', r'#.runtimeTypeCache[#] = #', JS_CURRENT_ISOLATE(), key, |
| 1461 runtimeType); | 1403 runtimeType); |
| 1462 } | 1404 } |
| 1463 return runtimeType; | 1405 return runtimeType; |
| 1464 } | 1406 } |
| 1465 | 1407 |
| 1466 String getRuntimeTypeString(var object) { | 1408 String getRuntimeTypeString(var object) { |
| 1467 var typeInfo = JS('Object', r'#.builtin$typeInfo', object); | 1409 var typeInfo = JS('Object', r'#.builtin$typeInfo', object); |
| 1468 return JS('String', r'#.runtimeType', typeInfo); | 1410 return JS('String', r'#.runtimeType', typeInfo); |
| 1469 } | 1411 } |
| OLD | NEW |