Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 // Patch file for dart:collection classes. | 5 // Patch file for dart:collection classes. |
| 6 import 'dart:_foreign_helper' show JS; | 6 import 'dart:_foreign_helper' show JS; |
| 7 import 'dart:_js_helper' show | 7 import 'dart:_js_helper' show |
| 8 fillLiteralMap, InternalMap, NoInline, NoThrows, patch, JsLinkedHashMap, | 8 fillLiteralMap, InternalMap, NoInline, NoThrows, patch, |
| 9 JsLinkedHashMap, Es6LinkedHashMap, | |
| 9 LinkedHashMapCell, LinkedHashMapKeyIterable, LinkedHashMapKeyIterator; | 10 LinkedHashMapCell, LinkedHashMapKeyIterable, LinkedHashMapKeyIterator; |
| 10 | 11 |
| 11 @patch | 12 @patch |
| 12 class HashMap<K, V> { | 13 class HashMap<K, V> { |
| 13 @patch | 14 @patch |
| 14 factory HashMap({ bool equals(K key1, K key2), | 15 factory HashMap({ bool equals(K key1, K key2), |
| 15 int hashCode(K key), | 16 int hashCode(K key), |
| 16 bool isValidKey(potentialKey) }) { | 17 bool isValidKey(potentialKey) }) { |
| 17 if (isValidKey == null) { | 18 if (isValidKey == null) { |
| 18 if (hashCode == null) { | 19 if (hashCode == null) { |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 if (identical(JS('var', '#[#]', bucket, i), key)) return i; | 380 if (identical(JS('var', '#[#]', bucket, i), key)) return i; |
| 380 } | 381 } |
| 381 return -1; | 382 return -1; |
| 382 } | 383 } |
| 383 } | 384 } |
| 384 | 385 |
| 385 class _CustomHashMap<K, V> extends _HashMap<K, V> { | 386 class _CustomHashMap<K, V> extends _HashMap<K, V> { |
| 386 final _Equality<K> _equals; | 387 final _Equality<K> _equals; |
| 387 final _Hasher<K> _hashCode; | 388 final _Hasher<K> _hashCode; |
| 388 final _Predicate _validKey; | 389 final _Predicate _validKey; |
| 390 | |
| 389 _CustomHashMap(this._equals, this._hashCode, bool validKey(potentialKey)) | 391 _CustomHashMap(this._equals, this._hashCode, bool validKey(potentialKey)) |
| 390 : _validKey = (validKey != null) ? validKey : ((v) => v is K); | 392 : _validKey = (validKey != null) ? validKey : ((v) => v is K); |
| 391 | 393 |
| 392 V operator[](Object key) { | 394 V operator[](Object key) { |
| 393 if (!_validKey(key)) return null; | 395 if (!_validKey(key)) return null; |
| 394 return super._get(key); | 396 return super._get(key); |
| 395 } | 397 } |
| 396 | 398 |
| 397 void operator[]=(K key, V value) { | 399 void operator[]=(K key, V value) { |
| 398 super._set(key, value); | 400 super._set(key, value); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 485 | 487 |
| 486 @patch | 488 @patch |
| 487 class LinkedHashMap<K, V> { | 489 class LinkedHashMap<K, V> { |
| 488 @patch | 490 @patch |
| 489 factory LinkedHashMap({ bool equals(K key1, K key2), | 491 factory LinkedHashMap({ bool equals(K key1, K key2), |
| 490 int hashCode(K key), | 492 int hashCode(K key), |
| 491 bool isValidKey(potentialKey) }) { | 493 bool isValidKey(potentialKey) }) { |
| 492 if (isValidKey == null) { | 494 if (isValidKey == null) { |
| 493 if (hashCode == null) { | 495 if (hashCode == null) { |
| 494 if (equals == null) { | 496 if (equals == null) { |
| 495 return new JsLinkedHashMap<K, V>(); | 497 if (JsLinkedHashMap.supportsEs6Maps) { |
| 498 return new Es6LinkedHashMap<K, V>(); | |
| 499 } else { | |
| 500 return new JsLinkedHashMap<K, V>(); | |
| 501 } | |
| 496 } | 502 } |
| 497 hashCode = _defaultHashCode; | 503 hashCode = _defaultHashCode; |
| 498 } else { | 504 } else { |
| 499 if (identical(identityHashCode, hashCode) && | 505 if (identical(identityHashCode, hashCode) && |
| 500 identical(identical, equals)) { | 506 identical(identical, equals)) { |
| 501 return new _LinkedIdentityHashMap<K, V>(); | 507 return new _LinkedIdentityHashMap<K, V>(); |
| 502 } | 508 } |
| 503 if (equals == null) { | 509 if (equals == null) { |
| 504 equals = _defaultEquals; | 510 equals = _defaultEquals; |
| 505 } | 511 } |
| 506 } | 512 } |
| 507 } else { | 513 } else { |
| 508 if (hashCode == null) { | 514 if (hashCode == null) { |
| 509 hashCode = _defaultHashCode; | 515 hashCode = _defaultHashCode; |
| 510 } | 516 } |
| 511 if (equals == null) { | 517 if (equals == null) { |
| 512 equals = _defaultEquals; | 518 equals = _defaultEquals; |
| 513 } | 519 } |
| 514 } | 520 } |
| 515 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); | 521 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); |
| 516 } | 522 } |
| 517 | 523 |
| 518 @patch | 524 @patch |
| 519 factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>; | 525 factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>; |
| 520 | 526 |
| 521 // Private factory constructor called by generated code for map literals. | 527 // Private factory constructor called by generated code for map literals. |
| 522 @NoInline() | 528 @NoInline() |
| 523 factory LinkedHashMap._literal(List keyValuePairs) { | 529 factory LinkedHashMap._literal(List keyValuePairs) { |
| 524 return fillLiteralMap(keyValuePairs, new JsLinkedHashMap<K, V>()); | 530 Map map = JsLinkedHashMap.supportsEs6Maps |
|
Vyacheslav Egorov (Google)
2015/03/26 00:03:57
Can this just call some force-inline static method
Harry Terkelsen
2015/03/26 00:40:06
Won't that require generic methods?
floitsch
2015/03/26 00:53:24
:)
I wondered the same, and had already started. T
| |
| 531 ? new Es6LinkedHashMap<K, V>() | |
| 532 : new JsLinkedHashMap<K, V>(); | |
| 533 return fillLiteralMap(keyValuePairs, map); | |
| 525 } | 534 } |
| 526 | 535 |
| 527 // Private factory constructor called by generated code for map literals. | 536 // Private factory constructor called by generated code for map literals. |
| 528 @NoThrows() @NoInline() | 537 @NoThrows() @NoInline() |
| 529 factory LinkedHashMap._empty() { | 538 factory LinkedHashMap._empty() { |
| 530 return new JsLinkedHashMap<K, V>(); | 539 return JsLinkedHashMap.supportsEs6Maps |
| 540 ? new Es6LinkedHashMap<K, V>() | |
| 541 : new JsLinkedHashMap<K, V>(); | |
| 531 } | 542 } |
| 532 } | 543 } |
| 533 | 544 |
| 545 // TODO(floitsch): use ES6 Maps when available. | |
| 534 class _LinkedIdentityHashMap<K, V> extends JsLinkedHashMap<K, V> { | 546 class _LinkedIdentityHashMap<K, V> extends JsLinkedHashMap<K, V> { |
| 547 | |
|
Harry Terkelsen
2015/03/26 00:40:07
unnecessary blank line
floitsch
2015/03/26 00:53:24
Done.
| |
| 535 int internalComputeHashCode(var key) { | 548 int internalComputeHashCode(var key) { |
| 536 // We force the hash codes to be unsigned 30-bit integers to avoid | 549 // We force the hash codes to be unsigned 30-bit integers to avoid |
| 537 // issues with problematic keys like '__proto__'. Another option | 550 // issues with problematic keys like '__proto__'. Another option |
| 538 // would be to throw an exception if the hash code isn't a number. | 551 // would be to throw an exception if the hash code isn't a number. |
| 539 return JS('int', '# & 0x3ffffff', identityHashCode(key)); | 552 return JS('int', '# & 0x3ffffff', identityHashCode(key)); |
| 540 } | 553 } |
| 541 | 554 |
| 542 int internalFindBucketIndex(var bucket, var key) { | 555 int internalFindBucketIndex(var bucket, var key) { |
| 543 if (bucket == null) return -1; | 556 if (bucket == null) return -1; |
| 544 int length = JS('int', '#.length', bucket); | 557 int length = JS('int', '#.length', bucket); |
| 545 for (int i = 0; i < length; i++) { | 558 for (int i = 0; i < length; i++) { |
| 546 LinkedHashMapCell cell = JS('var', '#[#]', bucket, i); | 559 LinkedHashMapCell cell = JS('var', '#[#]', bucket, i); |
| 547 if (identical(cell.hashMapCellKey, key)) return i; | 560 if (identical(cell.hashMapCellKey, key)) return i; |
| 548 } | 561 } |
| 549 return -1; | 562 return -1; |
| 550 } | 563 } |
| 551 } | 564 } |
| 552 | 565 |
| 566 // TODO(floitsch): use ES6 maps when available. | |
| 553 class _LinkedCustomHashMap<K, V> extends JsLinkedHashMap<K, V> { | 567 class _LinkedCustomHashMap<K, V> extends JsLinkedHashMap<K, V> { |
| 554 final _Equality<K> _equals; | 568 final _Equality<K> _equals; |
| 555 final _Hasher<K> _hashCode; | 569 final _Hasher<K> _hashCode; |
| 556 final _Predicate _validKey; | 570 final _Predicate _validKey; |
| 571 | |
| 557 _LinkedCustomHashMap(this._equals, this._hashCode, | 572 _LinkedCustomHashMap(this._equals, this._hashCode, |
| 558 bool validKey(potentialKey)) | 573 bool validKey(potentialKey)) |
| 559 : _validKey = (validKey != null) ? validKey : ((v) => v is K); | 574 : _validKey = (validKey != null) ? validKey : ((v) => v is K); |
| 560 | 575 |
| 576 | |
|
Harry Terkelsen
2015/03/26 00:40:06
unnecessary blank line
floitsch
2015/03/26 00:53:24
Done.
| |
| 561 V operator[](Object key) { | 577 V operator[](Object key) { |
| 562 if (!_validKey(key)) return null; | 578 if (!_validKey(key)) return null; |
| 563 return super.internalGet(key); | 579 return super.internalGet(key); |
| 564 } | 580 } |
| 565 | 581 |
| 566 void operator[]=(K key, V value) { | 582 void operator[]=(K key, V value) { |
| 567 super.internalSet(key, value); | 583 super.internalSet(key, value); |
| 568 } | 584 } |
| 569 | 585 |
| 570 bool containsKey(Object key) { | 586 bool containsKey(Object key) { |
| (...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1458 } else if (_cell == null) { | 1474 } else if (_cell == null) { |
| 1459 _current = null; | 1475 _current = null; |
| 1460 return false; | 1476 return false; |
| 1461 } else { | 1477 } else { |
| 1462 _current = _cell._element; | 1478 _current = _cell._element; |
| 1463 _cell = _cell._next; | 1479 _cell = _cell._next; |
| 1464 return true; | 1480 return true; |
| 1465 } | 1481 } |
| 1466 } | 1482 } |
| 1467 } | 1483 } |
| OLD | NEW |