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 |