OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 // Patch file for dart:core classes. | |
6 import "dart:_internal" as _symbol_dev; | |
7 import 'dart:_interceptors'; | |
8 import 'dart:_js_helper' show patch, | |
9 patch_new, | |
10 patch_old, | |
11 checkInt, | |
12 getRuntimeType, | |
13 jsonEncodeNative, | |
14 JSSyntaxRegExp, | |
15 Primitives, | |
16 ConstantMap, | |
17 stringJoinUnchecked, | |
18 objectHashCode, | |
19 Closure; | |
20 | |
21 import 'dart:_native_typed_data' show NativeUint8List; | |
22 | |
23 String _symbolToString(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); | |
24 | |
25 _symbolMapToStringMap(Map<Symbol, dynamic> map) { | |
26 if (map == null) return null; | |
27 var result = new Map<String, dynamic>(); | |
28 map.forEach((Symbol key, value) { | |
29 result[_symbolToString(key)] = value; | |
30 }); | |
31 return result; | |
32 } | |
33 | |
34 @patch | |
35 int identityHashCode(Object object) => objectHashCode(object); | |
36 | |
37 // Patch for Object implementation. | |
38 @patch | |
39 class Object { | |
40 @patch | |
41 int get hashCode => Primitives.objectHashCode(this); | |
42 | |
43 | |
44 @patch | |
45 String toString() => Primitives.objectToHumanReadableString(this); | |
46 | |
47 @patch | |
48 dynamic noSuchMethod(Invocation invocation) { | |
49 throw new NoSuchMethodError( | |
50 this, | |
51 invocation.memberName, | |
52 invocation.positionalArguments, | |
53 invocation.namedArguments); | |
54 } | |
55 | |
56 @patch | |
57 Type get runtimeType => getRuntimeType(this); | |
58 } | |
59 | |
60 // Patch for Function implementation. | |
61 @patch | |
62 class Function { | |
63 @patch_old | |
64 static apply(Function function, | |
65 List positionalArguments, | |
66 [Map<Symbol, dynamic> namedArguments]) { | |
67 return Primitives.applyFunction( | |
68 function, positionalArguments, | |
69 namedArguments == null ? null : _toMangledNames(namedArguments)); | |
70 } | |
71 | |
72 @patch_new | |
73 static apply(Function function, | |
74 List positionalArguments, | |
75 [Map<Symbol, dynamic> namedArguments]) { | |
76 return Primitives.applyFunctionNewEmitter(function, positionalArguments, | |
77 namedArguments == null ? null : _symbolMapToStringMap(namedArguments)); | |
78 } | |
79 | |
80 static Map<String, dynamic> _toMangledNames( | |
81 Map<Symbol, dynamic> namedArguments) { | |
82 Map<String, dynamic> result = {}; | |
83 namedArguments.forEach((symbol, value) { | |
84 result[_symbolToString(symbol)] = value; | |
85 }); | |
86 return result; | |
87 } | |
88 } | |
89 | |
90 // Patch for Expando implementation. | |
91 @patch | |
92 class Expando<T> { | |
93 @patch | |
94 Expando([String name]) : this.name = name; | |
95 | |
96 @patch | |
97 T operator[](Object object) { | |
98 var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME); | |
99 return (values == null) ? null : Primitives.getProperty(values, _getKey()); | |
100 } | |
101 | |
102 @patch | |
103 void operator[]=(Object object, T value) { | |
104 var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME); | |
105 if (values == null) { | |
106 values = new Object(); | |
107 Primitives.setProperty(object, _EXPANDO_PROPERTY_NAME, values); | |
108 } | |
109 Primitives.setProperty(values, _getKey(), value); | |
110 } | |
111 | |
112 String _getKey() { | |
113 String key = Primitives.getProperty(this, _KEY_PROPERTY_NAME); | |
114 if (key == null) { | |
115 key = "expando\$key\$${_keyCount++}"; | |
116 Primitives.setProperty(this, _KEY_PROPERTY_NAME, key); | |
117 } | |
118 return key; | |
119 } | |
120 | |
121 static const String _KEY_PROPERTY_NAME = 'expando\$key'; | |
122 static const String _EXPANDO_PROPERTY_NAME = 'expando\$values'; | |
123 static int _keyCount = 0; | |
124 } | |
125 | |
126 @patch | |
127 class int { | |
128 @patch | |
129 static int parse(String source, | |
130 { int radix, | |
131 int onError(String source) }) { | |
132 return Primitives.parseInt(source, radix, onError); | |
133 } | |
134 | |
135 @patch | |
136 factory int.fromEnvironment(String name, {int defaultValue}) { | |
137 throw new UnsupportedError( | |
138 'int.fromEnvironment can only be used as a const constructor'); | |
139 } | |
140 } | |
141 | |
142 @patch | |
143 class double { | |
144 @patch | |
145 static double parse(String source, | |
146 [double onError(String source)]) { | |
147 return Primitives.parseDouble(source, onError); | |
148 } | |
149 } | |
150 | |
151 @patch | |
152 class Error { | |
153 @patch | |
154 static String _objectToString(Object object) { | |
155 // Closures all have useful and safe toString methods. | |
156 if (object is Closure) return object.toString(); | |
157 return Primitives.objectToHumanReadableString(object); | |
158 } | |
159 | |
160 @patch | |
161 static String _stringToSafeString(String string) { | |
162 return jsonEncodeNative(string); | |
163 } | |
164 | |
165 @patch | |
166 StackTrace get stackTrace => Primitives.extractStackTrace(this); | |
167 } | |
168 | |
169 // Patch for DateTime implementation. | |
170 @patch | |
171 class DateTime { | |
172 @patch | |
173 DateTime._internal(int year, | |
174 int month, | |
175 int day, | |
176 int hour, | |
177 int minute, | |
178 int second, | |
179 int millisecond, | |
180 bool isUtc) | |
181 // checkBool is manually inlined here because dart2js doesn't inline it | |
182 // and [isUtc] is usually a constant. | |
183 : this.isUtc = isUtc is bool | |
184 ? isUtc | |
185 : throw new ArgumentError.value(isUtc, 'isUtc'), | |
186 millisecondsSinceEpoch = checkInt(Primitives.valueFromDecomposedDate( | |
187 year, month, day, hour, minute, second, millisecond, isUtc)); | |
188 | |
189 @patch | |
190 DateTime._now() | |
191 : isUtc = false, | |
192 millisecondsSinceEpoch = Primitives.dateNow(); | |
193 | |
194 @patch | |
195 static int _brokenDownDateToMillisecondsSinceEpoch( | |
196 int year, int month, int day, int hour, int minute, int second, | |
197 int millisecond, bool isUtc) { | |
198 return Primitives.valueFromDecomposedDate( | |
199 year, month, day, hour, minute, second, millisecond, isUtc); | |
200 } | |
201 | |
202 @patch | |
203 String get timeZoneName { | |
204 if (isUtc) return "UTC"; | |
205 return Primitives.getTimeZoneName(this); | |
206 } | |
207 | |
208 @patch | |
209 Duration get timeZoneOffset { | |
210 if (isUtc) return new Duration(); | |
211 return new Duration(minutes: Primitives.getTimeZoneOffsetInMinutes(this)); | |
212 } | |
213 | |
214 @patch | |
215 int get year => Primitives.getYear(this); | |
216 | |
217 @patch | |
218 int get month => Primitives.getMonth(this); | |
219 | |
220 @patch | |
221 int get day => Primitives.getDay(this); | |
222 | |
223 @patch | |
224 int get hour => Primitives.getHours(this); | |
225 | |
226 @patch | |
227 int get minute => Primitives.getMinutes(this); | |
228 | |
229 @patch | |
230 int get second => Primitives.getSeconds(this); | |
231 | |
232 @patch | |
233 int get millisecond => Primitives.getMilliseconds(this); | |
234 | |
235 @patch | |
236 int get weekday => Primitives.getWeekday(this); | |
237 } | |
238 | |
239 | |
240 // Patch for Stopwatch implementation. | |
241 @patch | |
242 class Stopwatch { | |
243 @patch | |
244 static void _initTicker() { | |
245 Primitives.initTicker(); | |
246 _frequency = Primitives.timerFrequency; | |
247 } | |
248 | |
249 @patch | |
250 static int _now() => Primitives.timerTicks(); | |
251 } | |
252 | |
253 class _ListConstructorSentinel extends JSInt { | |
254 const _ListConstructorSentinel(); | |
255 } | |
256 | |
257 // Patch for List implementation. | |
258 @patch | |
259 class List<E> { | |
260 @patch | |
261 factory List([int length = const _ListConstructorSentinel()]) { | |
262 if (length == const _ListConstructorSentinel()) { | |
263 return new JSArray<E>.emptyGrowable(); | |
264 } | |
265 return new JSArray<E>.fixed(length); | |
266 } | |
267 | |
268 @patch | |
269 factory List.filled(int length, E fill) { | |
270 List result = new JSArray<E>.fixed(length); | |
271 if (length != 0 && fill != null) { | |
272 for (int i = 0; i < result.length; i++) { | |
273 result[i] = fill; | |
274 } | |
275 } | |
276 return result; | |
277 } | |
278 | |
279 @patch | |
280 factory List.from(Iterable elements, { bool growable: true }) { | |
281 List<E> list = new List<E>(); | |
282 for (E e in elements) { | |
283 list.add(e); | |
284 } | |
285 if (growable) return list; | |
286 return makeListFixedLength(list); | |
287 } | |
288 | |
289 @patch | |
290 factory List.unmodifiable(Iterable elements) { | |
291 List result = new List<E>.from(elements, growable: false); | |
292 return makeFixedListUnmodifiable(result); | |
293 } | |
294 } | |
295 | |
296 @patch | |
297 class Map<K, V> { | |
298 @patch | |
299 factory Map.unmodifiable(Map other) = ConstantMap<K, V>.from; | |
300 } | |
301 | |
302 @patch | |
303 class String { | |
304 @patch | |
305 factory String.fromCharCodes(Iterable<int> charCodes, | |
306 [int start = 0, int end]) { | |
307 | |
308 if (charCodes is JSArray) { | |
309 return _stringFromJSArray(charCodes, start, end); | |
310 } | |
311 if (charCodes is NativeUint8List) { | |
312 return _stringFromUint8List(charCodes, start, end); | |
313 } | |
314 return _stringFromIterable(charCodes, start, end); | |
315 } | |
316 | |
317 @patch | |
318 factory String.fromCharCode(int charCode) { | |
319 return Primitives.stringFromCharCode(charCode); | |
320 } | |
321 | |
322 @patch | |
323 factory String.fromEnvironment(String name, {String defaultValue}) { | |
324 throw new UnsupportedError( | |
325 'String.fromEnvironment can only be used as a const constructor'); | |
326 } | |
327 | |
328 static String _stringFromJSArray(List list, int start, int endOrNull) { | |
329 int len = list.length; | |
330 int end = RangeError.checkValidRange(start, endOrNull, len); | |
331 if (start > 0 || end < len) { | |
332 list = list.sublist(start, end); | |
333 } | |
334 return Primitives.stringFromCharCodes(list); | |
335 } | |
336 | |
337 static String _stringFromUint8List( | |
338 NativeUint8List charCodes, int start, int endOrNull) { | |
339 int len = charCodes.length; | |
340 int end = RangeError.checkValidRange(start, endOrNull, len); | |
341 return Primitives.stringFromNativeUint8List(charCodes, start, end); | |
342 } | |
343 | |
344 static String _stringFromIterable(Iterable<int> charCodes, | |
345 int start, int end) { | |
346 if (start < 0) throw new RangeError.range(start, 0, charCodes.length); | |
347 if (end != null && end < start) { | |
348 throw new RangeError.range(end, start, charCodes.length); | |
349 } | |
350 var it = charCodes.iterator; | |
351 for (int i = 0; i < start; i++) { | |
352 if (!it.moveNext()) { | |
353 throw new RangeError.range(start, 0, i); | |
354 } | |
355 } | |
356 var list = []; | |
357 if (end == null) { | |
358 while (it.moveNext()) list.add(it.current); | |
359 } else { | |
360 for (int i = start; i < end; i++) { | |
361 if (!it.moveNext()) { | |
362 throw new RangeError.range(end, start, i); | |
363 } | |
364 list.add(it.current); | |
365 } | |
366 } | |
367 return Primitives.stringFromCharCodes(list); | |
368 } | |
369 } | |
370 | |
371 @patch | |
372 class bool { | |
373 @patch | |
374 factory bool.fromEnvironment(String name, {bool defaultValue: false}) { | |
375 throw new UnsupportedError( | |
376 'bool.fromEnvironment can only be used as a const constructor'); | |
377 } | |
378 } | |
379 | |
380 @patch | |
381 class RegExp { | |
382 @patch | |
383 factory RegExp(String source, | |
384 {bool multiLine: false, | |
385 bool caseSensitive: true}) | |
386 => new JSSyntaxRegExp(source, | |
387 multiLine: multiLine, | |
388 caseSensitive: caseSensitive); | |
389 } | |
390 | |
391 // Patch for 'identical' function. | |
392 @patch | |
393 bool identical(Object a, Object b) { | |
394 return Primitives.identicalImplementation(a, b); | |
395 } | |
396 | |
397 @patch | |
398 class StringBuffer { | |
399 String _contents; | |
400 | |
401 @patch | |
402 StringBuffer([Object content = ""]) : _contents = '$content'; | |
403 | |
404 @patch | |
405 int get length => _contents.length; | |
406 | |
407 @patch | |
408 void write(Object obj) { | |
409 _writeString('$obj'); | |
410 } | |
411 | |
412 @patch | |
413 void writeCharCode(int charCode) { | |
414 _writeString(new String.fromCharCode(charCode)); | |
415 } | |
416 | |
417 @patch | |
418 void writeAll(Iterable objects, [String separator = ""]) { | |
419 _contents = _writeAll(_contents, objects, separator); | |
420 } | |
421 | |
422 @patch | |
423 void writeln([Object obj = ""]) { | |
424 _writeString('$obj\n'); | |
425 } | |
426 | |
427 @patch | |
428 void clear() { | |
429 _contents = ""; | |
430 } | |
431 | |
432 @patch | |
433 String toString() => Primitives.flattenString(_contents); | |
434 | |
435 void _writeString(str) { | |
436 _contents = Primitives.stringConcatUnchecked(_contents, str); | |
437 } | |
438 | |
439 static String _writeAll(String string, Iterable objects, String separator) { | |
440 Iterator iterator = objects.iterator; | |
441 if (!iterator.moveNext()) return string; | |
442 if (separator.isEmpty) { | |
443 do { | |
444 string = _writeOne(string, iterator.current); | |
445 } while (iterator.moveNext()); | |
446 } else { | |
447 string = _writeOne(string, iterator.current); | |
448 while (iterator.moveNext()) { | |
449 string = _writeOne(string, separator); | |
450 string = _writeOne(string, iterator.current); | |
451 } | |
452 } | |
453 return string; | |
454 } | |
455 | |
456 static String _writeOne(String string, Object obj) { | |
457 return Primitives.stringConcatUnchecked(string, '$obj'); | |
458 } | |
459 } | |
460 | |
461 @patch | |
462 class NoSuchMethodError { | |
463 @patch | |
464 String toString() { | |
465 StringBuffer sb = new StringBuffer(); | |
466 String comma = ''; | |
467 if (_arguments != null) { | |
468 for (var argument in _arguments) { | |
469 sb.write(comma); | |
470 sb.write(Error.safeToString(argument)); | |
471 comma = ', '; | |
472 } | |
473 } | |
474 if (_namedArguments != null) { | |
475 _namedArguments.forEach((Symbol key, var value) { | |
476 sb.write(comma); | |
477 sb.write(_symbolToString(key)); | |
478 sb.write(": "); | |
479 sb.write(Error.safeToString(value)); | |
480 comma = ', '; | |
481 }); | |
482 } | |
483 String memberName = _symbolToString(_memberName); | |
484 String receiverText = Error.safeToString(_receiver); | |
485 String actualParameters = '$sb'; | |
486 if (_existingArgumentNames == null) { | |
487 return "NoSuchMethodError: method not found: '$memberName'\n" | |
488 "Receiver: ${receiverText}\n" | |
489 "Arguments: [$actualParameters]"; | |
490 } else { | |
491 String formalParameters = _existingArgumentNames.join(', '); | |
492 return "NoSuchMethodError: incorrect number of arguments passed to " | |
493 "method named '$memberName'\n" | |
494 "Receiver: ${receiverText}\n" | |
495 "Tried calling: $memberName($actualParameters)\n" | |
496 "Found: $memberName($formalParameters)"; | |
497 } | |
498 } | |
499 } | |
500 | |
501 @patch | |
502 class Uri { | |
503 @patch | |
504 static bool get _isWindows => false; | |
505 | |
506 @patch | |
507 static Uri get base { | |
508 String uri = Primitives.currentUri(); | |
509 if (uri != null) return Uri.parse(uri); | |
510 throw new UnsupportedError("'Uri.base' is not supported"); | |
511 } | |
512 } | |
513 | |
514 @patch | |
515 class Resource { | |
516 @patch | |
517 const factory Resource(String uri) = _Resource; | |
518 } | |
519 | |
520 Uri _resolvePackageUri(Uri packageUri) { | |
521 assert(packageUri.scheme == "package"); | |
522 if (packageUri.hasAuthority) { | |
523 throw new ArgumentError("Package-URI must not have a host: $packageUri"); | |
524 } | |
525 var resolved = Uri.base.resolve("packages/${packageUri.path}"); | |
526 return resolved; | |
527 } | |
528 | |
529 class _Resource implements Resource { | |
530 final String _location; | |
531 | |
532 const _Resource(String uri) : _location = uri; | |
533 | |
534 Uri get uri => Uri.base.resolve(_location); | |
535 | |
536 Stream<List<int>> openRead() { | |
537 Uri uri = this.uri; | |
538 if (uri.scheme == "package") { | |
539 uri = _resolvePackageUri(uri); | |
540 } | |
541 if (uri.scheme == "http" || uri.scheme == "https") { | |
542 return _readAsStream(uri); | |
543 } | |
544 throw new StateError("Unable to find resource, unknown scheme: $_location"); | |
545 } | |
546 | |
547 Future<List<int>> readAsBytes() { | |
548 Uri uri = this.uri; | |
549 if (uri.scheme == "package") { | |
550 uri = _resolvePackageUri(uri); | |
551 } | |
552 if (uri.scheme == "http" || uri.scheme == "https") { | |
553 return _readAsBytes(uri); | |
554 } | |
555 throw new StateError("Unable to find resource, unknown scheme: $_location"); | |
556 } | |
557 | |
558 Future<String> readAsString({Encoding encoding: UTF8}) { | |
559 Uri uri = this.uri; | |
560 if (uri.scheme == "package") { | |
561 uri = _resolvePackageUri(uri); | |
562 } | |
563 if (uri.scheme == "http" || uri.scheme == "https") { | |
564 return _readAsString(uri); | |
565 } | |
566 throw new StateError("Unable to find resource, unknown scheme: $_location"); | |
567 } | |
568 | |
569 Stream<List<int>> _readAsStream(Uri uri) { | |
570 throw new UnimplementedError("Streaming bytes via HTTP"); | |
571 } | |
572 | |
573 Future<List<int>> _readAsBytes(Uri uri) { | |
574 throw new UnimplementedError("Reading bytes via HTTP"); | |
575 } | |
576 | |
577 Future<String> _readAsString(Uri uri) { | |
578 throw new UnimplementedError("Reading string via HTTP"); | |
579 } | |
580 } | |
OLD | NEW |