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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/lib/js_helper.dart

Issue 11783009: Big merge from experimental to bleeding edge. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 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) 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 'dart:collection'; 7 import 'dart:collection';
8 8
9 part 'constant_map.dart'; 9 part 'constant_map.dart';
10 part 'native_helper.dart'; 10 part 'native_helper.dart';
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 throw new UnsupportedError(reason); 332 throw new UnsupportedError(reason);
333 } 333 }
334 } 334 }
335 335
336 String S(value) { 336 String S(value) {
337 var res = value.toString(); 337 var res = value.toString();
338 if (res is !String) throw new ArgumentError(value); 338 if (res is !String) throw new ArgumentError(value);
339 return res; 339 return res;
340 } 340 }
341 341
342 class ListIterator<T> implements Iterator<T> {
343 int i;
344 List<T> list;
345 ListIterator(List<T> this.list) : i = 0;
346 bool get hasNext => i < JS('int', r'#.length', list);
347 T next() {
348 if (!hasNext) throw new StateError("No more elements");
349 var value = JS('', r'#[#]', list, i);
350 i += 1;
351 return value;
352 }
353 }
354
355 createInvocationMirror(name, internalName, type, arguments, argumentNames) => 342 createInvocationMirror(name, internalName, type, arguments, argumentNames) =>
356 new JSInvocationMirror(name, internalName, type, arguments, argumentNames); 343 new JSInvocationMirror(name, internalName, type, arguments, argumentNames);
357 344
358 class JSInvocationMirror implements InvocationMirror { 345 class JSInvocationMirror implements InvocationMirror {
359 static const METHOD = 0; 346 static const METHOD = 0;
360 static const GETTER = 1; 347 static const GETTER = 1;
361 static const SETTER = 2; 348 static const SETTER = 2;
362 349
363 final String memberName; 350 final String memberName;
364 final String _internalName; 351 final String _internalName;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 JS('void', r'print(#)', string); 441 JS('void', r'print(#)', string);
455 return; 442 return;
456 } 443 }
457 444
458 // This is somewhat nasty, but we don't want to drag in a bunch of 445 // This is somewhat nasty, but we don't want to drag in a bunch of
459 // dependencies to handle a situation that cannot happen. So we 446 // dependencies to handle a situation that cannot happen. So we
460 // avoid using Dart [:throw:] and Dart [toString]. 447 // avoid using Dart [:throw:] and Dart [toString].
461 JS('void', "throw 'Unable to print message: ' + String(#)", string); 448 JS('void', "throw 'Unable to print message: ' + String(#)", string);
462 } 449 }
463 450
464 static int parseInt(String string) { 451 static void _throwFormatException(String string) {
465 checkString(string); 452 throw new FormatException(string);
466 var match = JS('=List|Null',
467 r'/^\s*[+-]?(?:0(x)[a-f0-9]+|\d+)\s*$/i.exec(#)',
468 string);
469 if (match == null) {
470 throw new FormatException(string);
471 }
472 var base = 10;
473 if (match[1] != null) base = 16;
474 var result = JS('num', r'parseInt(#, #)', string, base);
475 if (result.isNaN) throw new FormatException(string);
476 return result;
477 } 453 }
478 454
479 static double parseDouble(String string) { 455 static int parseInt(String source,
480 checkString(string); 456 int radix,
457 int handleError(String source)) {
458 if (handleError == null) handleError = _throwFormatException;
459
460 checkString(source);
461 var match = JS('=List|Null',
462 r'/^\s*[+-]?((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$/i.exec(#)',
463 source);
464 int digitsIndex = 1;
465 int hexIndex = 2;
466 int decimalIndex = 3;
467 int nonDecimalHexIndex = 4;
468 if (radix == null) {
469 radix = 10;
470 if (match != null) {
471 if (match[hexIndex] != null) {
472 // Cannot fail because we know that the digits are all hex.
473 return JS('num', r'parseInt(#, 16)', source);
474 }
475 if (match[decimalIndex] != null) {
476 // Cannot fail because we know that the digits are all decimal.
477 return JS('num', r'parseInt(#, 10)', source);
478 }
479 return handleError(source);
480 }
481 } else {
482 if (radix is! int) throw new ArgumentError("Radix is not an integer");
483 if (radix < 2 || radix > 36) {
484 throw new RangeError("Radix $radix not in range 2..36");
485 }
486 if (match != null) {
487 if (radix == 10 && match[decimalIndex] != null) {
488 // Cannot fail because we know that the digits are all decimal.
489 return JS('num', r'parseInt(#, 10)', source);
490 }
491 if (radix < 10 || match[decimalIndex] == null) {
492 // We know that the characters must be ASCII as otherwise the
493 // regexp wouldn't have matched. Calling toLowerCase is thus
494 // guaranteed to be a safe operation. If it wasn't ASCII, then
495 // "İ" would become "i", and we would accept it for radices greater
496 // than 18.
497 int maxCharCode;
498 if (radix <= 10) {
499 // Allow all digits less than the radix. For example 0, 1, 2 for
500 // radix 3.
501 // "0".charCodeAt(0) + radix - 1;
502 maxCharCode = 0x30 + radix - 1;
503 } else {
504 // Characters are located after the digits in ASCII. Therefore we
505 // only check for the character code. The regexp above made already
506 // sure that the string does not contain anything but digits or
507 // characters.
508 // "0".charCodeAt(0) + radix - 1;
509 maxCharCode = 0x61 + radix - 10 - 1;
510 }
511 String digitsPart = match[digitsIndex].toLowerCase();
512 for (int i = 0; i < digitsPart.length; i++) {
513 if (digitsPart.charCodeAt(i) > maxCharCode) {
514 return handleError(source);
515 }
516 }
517 }
518 }
519 }
520 if (match == null) return handleError(source);
521 return JS('num', r'parseInt(#, #)', source, radix);
522 }
523
524 static double parseDouble(String source, int handleError(String source)) {
525 checkString(source);
526 if (handleError == null) handleError = _throwFormatException;
481 // Notice that JS parseFloat accepts garbage at the end of the string. 527 // Notice that JS parseFloat accepts garbage at the end of the string.
482 // Accept, ignoring leading and trailing whitespace: 528 // Accept only:
483 // - NaN 529 // - NaN
484 // - [+/-]Infinity 530 // - [+/-]Infinity
485 // - a Dart double literal 531 // - a Dart double literal
532 // We do not allow leading or trailing whitespace.
486 if (!JS('bool', 533 if (!JS('bool',
487 r'/^\s*(?:NaN|[+-]?(?:Infinity|' 534 r'/^\s*(?:NaN|[+-]?(?:Infinity|'
488 r'(?:\.\d+|\d+(?:\.\d+)?)(?:[eE][+-]?\d+)?))\s*$/.test(#)', 535 r'(?:\.\d+|\d+(?:\.\d+)?)(?:[eE][+-]?\d+)?))\s*$/.test(#)',
489 string)) { 536 source)) {
490 throw new FormatException(string); 537 return handleError(source);
491 } 538 }
492 var result = JS('num', r'parseFloat(#)', string); 539 var result = JS('num', r'parseFloat(#)', source);
493 if (result.isNaN && string != 'NaN') { 540 if (result.isNaN && source != 'NaN') {
494 throw new FormatException(string); 541 return handleError(source);
495 } 542 }
496 return result; 543 return result;
497 } 544 }
498 545
499 /** [: r"$".charCodeAt(0) :] */ 546 /** [: r"$".charCodeAt(0) :] */
500 static const int DOLLAR_CHAR_VALUE = 36; 547 static const int DOLLAR_CHAR_VALUE = 36;
501 548
502 static String objectTypeName(Object object) { 549 static String objectTypeName(Object object) {
503 String name = constructorNameFallback(object); 550 String name = constructorNameFallback(object);
504 if (name == 'Object') { 551 if (name == 'Object') {
505 // Try to decompile the constructor by turning it into a string 552 // Try to decompile the constructor by turning it into a string
506 // and get the name out of that. If the decompiled name is a 553 // and get the name out of that. If the decompiled name is a
507 // string, we use that instead of the very generic 'Object'. 554 // string, we use that instead of the very generic 'Object'.
508 var decompiled = JS('var', r'#.match(/^\s*function\s*(\S*)\s*\(/)[1]', 555 var decompiled = JS('var', r'#.match(/^\s*function\s*(\S*)\s*\(/)[1]',
509 JS('var', r'String(#.constructor)', object)); 556 JS('var', r'String(#.constructor)', object));
510 if (decompiled is String) name = decompiled; 557 if (decompiled is String) name = decompiled;
511 } 558 }
512 // TODO(kasperl): If the namer gave us a fresh global name, we may 559 // TODO(kasperl): If the namer gave us a fresh global name, we may
513 // want to remove the numeric suffix that makes it unique too. 560 // want to remove the numeric suffix that makes it unique too.
514 if (identical(name.charCodeAt(0), DOLLAR_CHAR_VALUE)) name = name.substring( 1); 561 if (identical(name.charCodeAt(0), DOLLAR_CHAR_VALUE)) name = name.substring( 1);
515 return name; 562 return name;
516 } 563 }
517 564
518 static String objectToString(Object object) { 565 static String objectToString(Object object) {
519 String name = objectTypeName(object); 566 String name = objectTypeName(object);
520 return "Instance of '$name'"; 567 return "Instance of '$name'";
521 } 568 }
522 569
523 static List newList(length) { 570 static List newGrowableList(length) {
524 // TODO(sra): For good concrete type analysis we need the JS-type to 571 // TODO(sra): For good concrete type analysis we need the JS-type to
525 // specifically name the JavaScript Array implementation. 'List' matches 572 // specifically name the JavaScript Array implementation. 'List' matches
526 // all the dart:html types that implement List<T>. 573 // all the dart:html types that implement List<T>.
527 if (length == null) return JS('=List', r'new Array()'); 574 return JS('Object', r'new Array(#)', length);
528 if ((length is !int) || (length < 0)) { 575 }
529 throw new ArgumentError(length); 576
530 } 577 static List newFixedList(length) {
578 // TODO(sra): For good concrete type analysis we need the JS-type to
579 // specifically name the JavaScript Array implementation. 'List' matches
580 // all the dart:html types that implement List<T>.
531 var result = JS('=List', r'new Array(#)', length); 581 var result = JS('=List', r'new Array(#)', length);
532 JS('void', r'#.fixed$length = #', result, true); 582 JS('void', r'#.fixed$length = #', result, true);
533 return result; 583 return result;
534 } 584 }
535 585
536 static num dateNow() => JS('num', r'Date.now()'); 586 static num dateNow() => JS('num', r'Date.now()');
537 587
538 static num numMicroseconds() { 588 static num numMicroseconds() {
539 if (JS('bool', 'typeof window != "undefined" && window !== null')) { 589 if (JS('bool', 'typeof window != "undefined" && window !== null')) {
540 var performance = JS('var', 'window.performance'); 590 var performance = JS('var', 'window.performance');
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 } 898 }
849 899
850 checkString(value) { 900 checkString(value) {
851 if (value is !String) { 901 if (value is !String) {
852 throw new ArgumentError(value); 902 throw new ArgumentError(value);
853 } 903 }
854 return value; 904 return value;
855 } 905 }
856 906
857 class MathNatives { 907 class MathNatives {
858 static int parseInt(str) {
859 checkString(str);
860 if (!JS('bool',
861 r'/^\s*[+-]?(?:0[xX][abcdefABCDEF0-9]+|\d+)\s*$/.test(#)',
862 str)) {
863 throw new FormatException(str);
864 }
865 var trimmed = str.trim();
866 var base = 10;;
867 if ((trimmed.length > 2 && (trimmed[1] == 'x' || trimmed[1] == 'X')) ||
868 (trimmed.length > 3 && (trimmed[2] == 'x' || trimmed[2] == 'X'))) {
869 base = 16;
870 }
871 var ret = JS('num', r'parseInt(#, #)', trimmed, base);
872 if (ret.isNaN) throw new FormatException(str);
873 return ret;
874 }
875
876 static double parseDouble(String str) {
877 checkString(str);
878 var ret = JS('num', r'parseFloat(#)', str);
879 if (ret == 0 && (str.startsWith("0x") || str.startsWith("0X"))) {
880 // TODO(ahe): This is unspecified, but tested by co19.
881 ret = JS('num', r'parseInt(#)', str);
882 }
883 if (ret.isNaN && str != 'NaN' && str != '-NaN') {
884 throw new FormatException(str);
885 }
886 return ret;
887 }
888
889 static double sqrt(num value) 908 static double sqrt(num value)
890 => JS('double', r'Math.sqrt(#)', checkNum(value)); 909 => JS('double', r'Math.sqrt(#)', checkNum(value));
891 910
892 static double sin(num value) 911 static double sin(num value)
893 => JS('double', r'Math.sin(#)', checkNum(value)); 912 => JS('double', r'Math.sin(#)', checkNum(value));
894 913
895 static double cos(num value) 914 static double cos(num value)
896 => JS('double', r'Math.cos(#)', checkNum(value)); 915 => JS('double', r'Math.cos(#)', checkNum(value));
897 916
898 static double tan(num value) 917 static double tan(num value)
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 StackTrace(this.stack); 1096 StackTrace(this.stack);
1078 String toString() => stack != null ? stack : ''; 1097 String toString() => stack != null ? stack : '';
1079 } 1098 }
1080 1099
1081 1100
1082 /** 1101 /**
1083 * Called by generated code to build a map literal. [keyValuePairs] is 1102 * Called by generated code to build a map literal. [keyValuePairs] is
1084 * a list of key, value, key, value, ..., etc. 1103 * a list of key, value, key, value, ..., etc.
1085 */ 1104 */
1086 makeLiteralMap(List keyValuePairs) { 1105 makeLiteralMap(List keyValuePairs) {
1087 Iterator iterator = keyValuePairs.iterator(); 1106 Iterator iterator = keyValuePairs.iterator;
1088 Map result = new LinkedHashMap(); 1107 Map result = new LinkedHashMap();
1089 while (iterator.hasNext) { 1108 while (iterator.moveNext()) {
1090 String key = iterator.next(); 1109 String key = iterator.current;
1091 var value = iterator.next(); 1110 iterator.moveNext();
1111 var value = iterator.current;
1092 result[key] = value; 1112 result[key] = value;
1093 } 1113 }
1094 return result; 1114 return result;
1095 } 1115 }
1096 1116
1097 invokeClosure(Function closure, 1117 invokeClosure(Function closure,
1098 var isolate, 1118 var isolate,
1099 int numberOfArguments, 1119 int numberOfArguments,
1100 var arg1, 1120 var arg1,
1101 var arg2) { 1121 var arg2) {
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
1708 if (len != t.length) return false; 1728 if (len != t.length) return false;
1709 for (int i = 1; i < len; i++) { 1729 for (int i = 1; i < len; i++) {
1710 if (!isSubtype(s[i], t[i])) { 1730 if (!isSubtype(s[i], t[i])) {
1711 return false; 1731 return false;
1712 } 1732 }
1713 } 1733 }
1714 return true; 1734 return true;
1715 } 1735 }
1716 1736
1717 createRuntimeType(String name) => new TypeImpl(name); 1737 createRuntimeType(String name) => new TypeImpl(name);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698