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

Side by Side Diff: sdk/lib/_internal/lib/collection_patch.dart

Issue 23494027: Make LinkedHashMap also have a factory constructor and be customizable (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 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) 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 7
8 patch class HashMap<K, V> { 8 patch class HashMap<K, V> {
9 patch factory HashMap({ bool equals(K key1, K key2), int hashCode(K key) }) { 9 patch factory HashMap({ bool equals(K key1, K key2), int hashCode(K key) }) {
10 if (hashCode == null) { 10 if (hashCode == null) {
11 if (equals == null) { 11 if (equals == null) {
12 return new _HashMapImpl<K, V>(); 12 return new _Hash<K, V>();
13 } 13 }
14 if (identical(identical, equals)) { 14 if (identical(identical, equals)) {
15 return new _IdentityHashMap<K, V>(); 15 return new _IdentityHashMap<K, V>();
16 } 16 }
17 hashCode = _defaultHashCode; 17 hashCode = _defaultHashCode;
18 } else if (equals == null) { 18 } else if (equals == null) {
19 equals = _defaultEquals; 19 equals = _defaultEquals;
20 } 20 }
21 return new _CustomHashMap<K, V>(equals, hashCode); 21 return new _CustomHashMap<K, V>(equals, hashCode);
22 } 22 }
23 } 23 }
24 24
25 class _HashMapImpl<K, V> implements HashMap<K, V> { 25 class _Hash<K, V> implements HashMap<K, V> {
26 int _length = 0; 26 int _length = 0;
27 27
28 // The hash map contents are divided into three parts: one part for 28 // The hash map contents are divided into three parts: one part for
29 // string keys, one for numeric keys, and one for the rest. String 29 // string keys, one for numeric keys, and one for the rest. String
30 // and numeric keys map directly to their values, but the rest of 30 // and numeric keys map directly to their values, but the rest of
31 // the entries are stored in bucket lists of the form: 31 // the entries are stored in bucket lists of the form:
32 // 32 //
33 // [key-0, value-0, key-1, value-1, ...] 33 // [key-0, value-0, key-1, value-1, ...]
34 // 34 //
35 // where all keys in the same bucket share the same hash code. 35 // where all keys in the same bucket share the same hash code.
36 var _strings; 36 var _strings;
37 var _nums; 37 var _nums;
38 var _rest; 38 var _rest;
39 39
40 // When iterating over the hash map, it is very convenient to have a 40 // When iterating over the hash map, it is very convenient to have a
41 // list of all the keys. We cache that on the instance and clear the 41 // list of all the keys. We cache that on the instance and clear the
42 // the cache whenever the key set changes. This is also used to 42 // the cache whenever the key set changes. This is also used to
43 // guard against concurrent modifications. 43 // guard against concurrent modifications.
44 List _keys; 44 List _keys;
45 45
46 _HashMapImpl(); 46 _Hash();
47 47
48 int get length => _length; 48 int get length => _length;
49 bool get isEmpty => _length == 0; 49 bool get isEmpty => _length == 0;
50 bool get isNotEmpty => !isEmpty; 50 bool get isNotEmpty => !isEmpty;
51 51
52 Iterable<K> get keys { 52 Iterable<K> get keys {
53 return new HashMapKeyIterable<K>(this); 53 return new HashMapKeyIterable<K>(this);
54 } 54 }
55 55
56 Iterable<V> get values { 56 Iterable<V> get values {
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 var table = JS('var', 'Object.create(null)'); 318 var table = JS('var', 'Object.create(null)');
319 // Attempt to force the hash table into 'dictionary' mode by 319 // Attempt to force the hash table into 'dictionary' mode by
320 // adding a property to it and deleting it again. 320 // adding a property to it and deleting it again.
321 var temporaryKey = '<non-identifier-key>'; 321 var temporaryKey = '<non-identifier-key>';
322 _setTableEntry(table, temporaryKey, table); 322 _setTableEntry(table, temporaryKey, table);
323 _deleteTableEntry(table, temporaryKey); 323 _deleteTableEntry(table, temporaryKey);
324 return table; 324 return table;
325 } 325 }
326 } 326 }
327 327
328 class _IdentityHashMap<K, V> extends _HashMapImpl<K, V> { 328 class _IdentityHashMap<K, V> extends _Hash<K, V> {
329 int _findBucketIndex(var bucket, var key) { 329 int _findBucketIndex(var bucket, var key) {
330 if (bucket == null) return -1; 330 if (bucket == null) return -1;
331 int length = JS('int', '#.length', bucket); 331 int length = JS('int', '#.length', bucket);
332 for (int i = 0; i < length; i += 2) { 332 for (int i = 0; i < length; i += 2) {
333 if (identical(JS('var', '#[#]', bucket, i), key)) return i; 333 if (identical(JS('var', '#[#]', bucket, i), key)) return i;
334 } 334 }
335 return -1; 335 return -1;
336 } 336 }
337 } 337 }
338 338
339 class _CustomHashMap<K, V> extends _HashMapImpl<K, V> { 339 class _CustomHashMap<K, V> extends _Hash<K, V> {
340 final _Equality<K> _equals; 340 final _Equality<K> _equals;
341 final _Hasher<K> _hashCode; 341 final _Hasher<K> _hashCode;
342 _CustomHashMap(this._equals, this._hashCode); 342 _CustomHashMap(this._equals, this._hashCode);
343 343
344 int _computeHashCode(var key) { 344 int _computeHashCode(var key) {
345 // We force the hash codes to be unsigned 30-bit integers to avoid 345 // We force the hash codes to be unsigned 30-bit integers to avoid
346 // issues with problematic keys like '__proto__'. Another option 346 // issues with problematic keys like '__proto__'. Another option
347 // would be to throw an exception if the hash code isn't a number. 347 // would be to throw an exception if the hash code isn't a number.
348 return JS('int', '# & 0x3ffffff', _hashCode(key)); 348 return JS('int', '# & 0x3ffffff', _hashCode(key));
349 } 349 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 // TODO(kasperl): For now, we have to tell the type inferrer to 409 // TODO(kasperl): For now, we have to tell the type inferrer to
410 // treat the result of doing offset + 1 as an int. Otherwise, we 410 // treat the result of doing offset + 1 as an int. Otherwise, we
411 // get unnecessary bailout code. 411 // get unnecessary bailout code.
412 _offset = JS('int', '#', offset + 1); 412 _offset = JS('int', '#', offset + 1);
413 return true; 413 return true;
414 } 414 }
415 } 415 }
416 } 416 }
417 417
418 patch class LinkedHashMap<K, V> { 418 patch class LinkedHashMap<K, V> {
419 patch factory LinkedHashMap({ bool equals(K key1, K key2),
420 int hashCode(K key) }) {
421 if (hashCode == null) {
422 if (equals == null) {
423 return new _LinkedHash<K, V>();
424 }
425 if (identical(identical, equals)) {
426 return new _LinkedIdentityHashMap<K, V>();
427 }
428 hashCode = _defaultHashCode;
429 } else if (equals == null) {
430 equals = _defaultEquals;
431 }
432 return new _LinkedCustomHashMap<K, V>(equals, hashCode);
433 }
434 }
435
436 class _LinkedHash<K, V> implements LinkedHashMap<K, V> {
419 int _length = 0; 437 int _length = 0;
420 438
421 // The hash map contents are divided into three parts: one part for 439 // The hash map contents are divided into three parts: one part for
422 // string keys, one for numeric keys, and one for the rest. String 440 // string keys, one for numeric keys, and one for the rest. String
423 // and numeric keys map directly to their linked cells, but the rest 441 // and numeric keys map directly to their linked cells, but the rest
424 // of the entries are stored in bucket lists of the form: 442 // of the entries are stored in bucket lists of the form:
425 // 443 //
426 // [cell-0, cell-1, ...] 444 // [cell-0, cell-1, ...]
427 // 445 //
428 // where all keys in the same bucket share the same hash code. 446 // where all keys in the same bucket share the same hash code.
429 var _strings; 447 var _strings;
430 var _nums; 448 var _nums;
431 var _rest; 449 var _rest;
432 450
433 // The keys and values are stored in cells that are linked together 451 // The keys and values are stored in cells that are linked together
434 // to form a double linked list. 452 // to form a double linked list.
435 LinkedHashMapCell _first; 453 LinkedHashMapCell _first;
436 LinkedHashMapCell _last; 454 LinkedHashMapCell _last;
437 455
438 // We track the number of modifications done to the key set of the 456 // We track the number of modifications done to the key set of the
439 // hash map to be able to throw when the map is modified while being 457 // hash map to be able to throw when the map is modified while being
440 // iterated over. 458 // iterated over.
441 int _modifications = 0; 459 int _modifications = 0;
442 460
443 patch LinkedHashMap(); 461 _LinkedHash();
444 462
445 patch int get length => _length; 463 int get length => _length;
446 patch bool get isEmpty => _length == 0; 464 bool get isEmpty => _length == 0;
447 patch bool get isNotEmpty => !isEmpty; 465 bool get isNotEmpty => !isEmpty;
448 466
449 467
450 patch Iterable<K> get keys { 468 Iterable<K> get keys {
451 return new LinkedHashMapKeyIterable<K>(this); 469 return new LinkedHashMapKeyIterable<K>(this);
452 } 470 }
453 471
454 patch Iterable<V> get values { 472 Iterable<V> get values {
455 return keys.map((each) => this[each]); 473 return keys.map((each) => this[each]);
456 } 474 }
457 475
458 patch bool containsKey(Object key) { 476 bool containsKey(Object key) {
459 if (_isStringKey(key)) { 477 if (_isStringKey(key)) {
460 var strings = _strings; 478 var strings = _strings;
461 if (strings == null) return false; 479 if (strings == null) return false;
462 LinkedHashMapCell cell = _getTableEntry(strings, key); 480 LinkedHashMapCell cell = _getTableEntry(strings, key);
463 return cell != null; 481 return cell != null;
464 } else if (_isNumericKey(key)) { 482 } else if (_isNumericKey(key)) {
465 var nums = _nums; 483 var nums = _nums;
466 if (nums == null) return false; 484 if (nums == null) return false;
467 LinkedHashMapCell cell = _getTableEntry(nums, key); 485 LinkedHashMapCell cell = _getTableEntry(nums, key);
468 return cell != null; 486 return cell != null;
469 } else { 487 } else {
470 var rest = _rest; 488 var rest = _rest;
471 if (rest == null) return false; 489 if (rest == null) return false;
472 var bucket = _getBucket(rest, key); 490 var bucket = _getBucket(rest, key);
473 return _findBucketIndex(bucket, key) >= 0; 491 return _findBucketIndex(bucket, key) >= 0;
474 } 492 }
475 } 493 }
476 494
477 patch bool containsValue(Object value) { 495 bool containsValue(Object value) {
478 return keys.any((each) => this[each] == value); 496 return keys.any((each) => this[each] == value);
479 } 497 }
480 498
481 patch void addAll(Map<K, V> other) { 499 void addAll(Map<K, V> other) {
482 other.forEach((K key, V value) { 500 other.forEach((K key, V value) {
483 this[key] = value; 501 this[key] = value;
484 }); 502 });
485 } 503 }
486 504
487 patch V operator[](Object key) { 505 V operator[](Object key) {
488 if (_isStringKey(key)) { 506 if (_isStringKey(key)) {
489 var strings = _strings; 507 var strings = _strings;
490 if (strings == null) return null; 508 if (strings == null) return null;
491 LinkedHashMapCell cell = _getTableEntry(strings, key); 509 LinkedHashMapCell cell = _getTableEntry(strings, key);
492 return (cell == null) ? null : cell._value; 510 return (cell == null) ? null : cell._value;
493 } else if (_isNumericKey(key)) { 511 } else if (_isNumericKey(key)) {
494 var nums = _nums; 512 var nums = _nums;
495 if (nums == null) return null; 513 if (nums == null) return null;
496 LinkedHashMapCell cell = _getTableEntry(nums, key); 514 LinkedHashMapCell cell = _getTableEntry(nums, key);
497 return (cell == null) ? null : cell._value; 515 return (cell == null) ? null : cell._value;
498 } else { 516 } else {
499 var rest = _rest; 517 var rest = _rest;
500 if (rest == null) return null; 518 if (rest == null) return null;
501 var bucket = _getBucket(rest, key); 519 var bucket = _getBucket(rest, key);
502 int index = _findBucketIndex(bucket, key); 520 int index = _findBucketIndex(bucket, key);
503 if (index < 0) return null; 521 if (index < 0) return null;
504 LinkedHashMapCell cell = JS('var', '#[#]', bucket, index); 522 LinkedHashMapCell cell = JS('var', '#[#]', bucket, index);
505 return cell._value; 523 return cell._value;
506 } 524 }
507 } 525 }
508 526
509 patch void operator[]=(K key, V value) { 527 void operator[]=(K key, V value) {
510 if (_isStringKey(key)) { 528 if (_isStringKey(key)) {
511 var strings = _strings; 529 var strings = _strings;
512 if (strings == null) _strings = strings = _newHashTable(); 530 if (strings == null) _strings = strings = _newHashTable();
513 _addHashTableEntry(strings, key, value); 531 _addHashTableEntry(strings, key, value);
514 } else if (_isNumericKey(key)) { 532 } else if (_isNumericKey(key)) {
515 var nums = _nums; 533 var nums = _nums;
516 if (nums == null) _nums = nums = _newHashTable(); 534 if (nums == null) _nums = nums = _newHashTable();
517 _addHashTableEntry(nums, key, value); 535 _addHashTableEntry(nums, key, value);
518 } else { 536 } else {
519 var rest = _rest; 537 var rest = _rest;
520 if (rest == null) _rest = rest = _newHashTable(); 538 if (rest == null) _rest = rest = _newHashTable();
521 var hash = _computeHashCode(key); 539 var hash = _computeHashCode(key);
522 var bucket = JS('var', '#[#]', rest, hash); 540 var bucket = JS('var', '#[#]', rest, hash);
523 if (bucket == null) { 541 if (bucket == null) {
524 LinkedHashMapCell cell = _newLinkedCell(key, value); 542 LinkedHashMapCell cell = _newLinkedCell(key, value);
525 _setTableEntry(rest, hash, JS('var', '[#]', cell)); 543 _setTableEntry(rest, hash, JS('var', '[#]', cell));
526 } else { 544 } else {
527 int index = _findBucketIndex(bucket, key); 545 int index = _findBucketIndex(bucket, key);
528 if (index >= 0) { 546 if (index >= 0) {
529 LinkedHashMapCell cell = JS('var', '#[#]', bucket, index); 547 LinkedHashMapCell cell = JS('var', '#[#]', bucket, index);
530 cell._value = value; 548 cell._value = value;
531 } else { 549 } else {
532 LinkedHashMapCell cell = _newLinkedCell(key, value); 550 LinkedHashMapCell cell = _newLinkedCell(key, value);
533 JS('void', '#.push(#)', bucket, cell); 551 JS('void', '#.push(#)', bucket, cell);
534 } 552 }
535 } 553 }
536 } 554 }
537 } 555 }
538 556
539 patch V putIfAbsent(K key, V ifAbsent()) { 557 V putIfAbsent(K key, V ifAbsent()) {
540 if (containsKey(key)) return this[key]; 558 if (containsKey(key)) return this[key];
541 V value = ifAbsent(); 559 V value = ifAbsent();
542 this[key] = value; 560 this[key] = value;
543 return value; 561 return value;
544 } 562 }
545 563
546 patch V remove(Object key) { 564 V remove(Object key) {
547 if (_isStringKey(key)) { 565 if (_isStringKey(key)) {
548 return _removeHashTableEntry(_strings, key); 566 return _removeHashTableEntry(_strings, key);
549 } else if (_isNumericKey(key)) { 567 } else if (_isNumericKey(key)) {
550 return _removeHashTableEntry(_nums, key); 568 return _removeHashTableEntry(_nums, key);
551 } else { 569 } else {
552 var rest = _rest; 570 var rest = _rest;
553 if (rest == null) return null; 571 if (rest == null) return null;
554 var bucket = _getBucket(rest, key); 572 var bucket = _getBucket(rest, key);
555 int index = _findBucketIndex(bucket, key); 573 int index = _findBucketIndex(bucket, key);
556 if (index < 0) return null; 574 if (index < 0) return null;
557 // Use splice to remove the [cell] element at the index and 575 // Use splice to remove the [cell] element at the index and
558 // unlink the cell before returning its value. 576 // unlink the cell before returning its value.
559 LinkedHashMapCell cell = JS('var', '#.splice(#, 1)[0]', bucket, index); 577 LinkedHashMapCell cell = JS('var', '#.splice(#, 1)[0]', bucket, index);
560 _unlinkCell(cell); 578 _unlinkCell(cell);
561 // TODO(kasperl): Consider getting rid of the bucket list when 579 // TODO(kasperl): Consider getting rid of the bucket list when
562 // the length reaches zero. 580 // the length reaches zero.
563 return cell._value; 581 return cell._value;
564 } 582 }
565 } 583 }
566 584
567 patch void clear() { 585 void clear() {
568 if (_length > 0) { 586 if (_length > 0) {
569 _strings = _nums = _rest = _first = _last = null; 587 _strings = _nums = _rest = _first = _last = null;
570 _length = 0; 588 _length = 0;
571 _modified(); 589 _modified();
572 } 590 }
573 } 591 }
574 592
575 patch void forEach(void action(K key, V value)) { 593 void forEach(void action(K key, V value)) {
576 LinkedHashMapCell cell = _first; 594 LinkedHashMapCell cell = _first;
577 int modifications = _modifications; 595 int modifications = _modifications;
578 while (cell != null) { 596 while (cell != null) {
579 action(cell._key, cell._value); 597 action(cell._key, cell._value);
580 if (modifications != _modifications) { 598 if (modifications != _modifications) {
581 throw new ConcurrentModificationError(this); 599 throw new ConcurrentModificationError(this);
582 } 600 }
583 cell = cell._next; 601 cell = cell._next;
584 } 602 }
585 } 603 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 return key is String && key != '__proto__'; 666 return key is String && key != '__proto__';
649 } 667 }
650 668
651 static bool _isNumericKey(var key) { 669 static bool _isNumericKey(var key) {
652 // Only treat unsigned 30-bit integers as numeric keys. This way, 670 // Only treat unsigned 30-bit integers as numeric keys. This way,
653 // we avoid converting them to strings when we use them as keys in 671 // we avoid converting them to strings when we use them as keys in
654 // the JavaScript hash table object. 672 // the JavaScript hash table object.
655 return key is num && JS('bool', '(# & 0x3ffffff) === #', key, key); 673 return key is num && JS('bool', '(# & 0x3ffffff) === #', key, key);
656 } 674 }
657 675
658 static int _computeHashCode(var key) { 676 int _computeHashCode(var key) {
659 // We force the hash codes to be unsigned 30-bit integers to avoid 677 // We force the hash codes to be unsigned 30-bit integers to avoid
660 // issues with problematic keys like '__proto__'. Another option 678 // issues with problematic keys like '__proto__'. Another option
661 // would be to throw an exception if the hash code isn't a number. 679 // would be to throw an exception if the hash code isn't a number.
662 return JS('int', '# & 0x3ffffff', key.hashCode); 680 return JS('int', '# & 0x3ffffff', key.hashCode);
663 } 681 }
664 682
665 static _getTableEntry(var table, var key) { 683 static _getTableEntry(var table, var key) {
666 return JS('var', '#[#]', table, key); 684 return JS('var', '#[#]', table, key);
667 } 685 }
668 686
669 static void _setTableEntry(var table, var key, var value) { 687 static void _setTableEntry(var table, var key, var value) {
670 assert(value != null); 688 assert(value != null);
671 JS('void', '#[#] = #', table, key, value); 689 JS('void', '#[#] = #', table, key, value);
672 } 690 }
673 691
674 static void _deleteTableEntry(var table, var key) { 692 static void _deleteTableEntry(var table, var key) {
675 JS('void', 'delete #[#]', table, key); 693 JS('void', 'delete #[#]', table, key);
676 } 694 }
677 695
678 static List _getBucket(var table, var key) { 696 List _getBucket(var table, var key) {
679 var hash = _computeHashCode(key); 697 var hash = _computeHashCode(key);
680 return JS('var', '#[#]', table, hash); 698 return JS('var', '#[#]', table, hash);
681 } 699 }
682 700
683 static int _findBucketIndex(var bucket, var key) { 701 int _findBucketIndex(var bucket, var key) {
684 if (bucket == null) return -1; 702 if (bucket == null) return -1;
685 int length = JS('int', '#.length', bucket); 703 int length = JS('int', '#.length', bucket);
686 for (int i = 0; i < length; i++) { 704 for (int i = 0; i < length; i++) {
687 LinkedHashMapCell cell = JS('var', '#[#]', bucket, i); 705 LinkedHashMapCell cell = JS('var', '#[#]', bucket, i);
688 if (cell._key == key) return i; 706 if (cell._key == key) return i;
689 } 707 }
690 return -1; 708 return -1;
691 } 709 }
692 710
693 static _newHashTable() { 711 static _newHashTable() {
694 // Create a new JavaScript object to be used as a hash table. Use 712 // Create a new JavaScript object to be used as a hash table. Use
695 // Object.create to avoid the properties on Object.prototype 713 // Object.create to avoid the properties on Object.prototype
696 // showing up as entries. 714 // showing up as entries.
697 var table = JS('var', 'Object.create(null)'); 715 var table = JS('var', 'Object.create(null)');
698 // Attempt to force the hash table into 'dictionary' mode by 716 // Attempt to force the hash table into 'dictionary' mode by
699 // adding a property to it and deleting it again. 717 // adding a property to it and deleting it again.
700 var temporaryKey = '<non-identifier-key>'; 718 var temporaryKey = '<non-identifier-key>';
701 _setTableEntry(table, temporaryKey, table); 719 _setTableEntry(table, temporaryKey, table);
702 _deleteTableEntry(table, temporaryKey); 720 _deleteTableEntry(table, temporaryKey);
703 return table; 721 return table;
704 } 722 }
723
724 String toString() => Maps.mapToString(this);
725 }
726
727 class _LinkedIdentityHashMap<K, V> extends _LinkedHash<K, V> {
728 int _findBucketIndex(var bucket, var key) {
729 if (bucket == null) return -1;
730 int length = JS('int', '#.length', bucket);
731 for (int i = 0; i < length; i++) {
732 LinkedHashMapCell cell = JS('var', '#[#]', bucket, i);
733 if (identical(cell._key, key)) return i;
734 }
735 return -1;
736 }
737 }
738
739 class _LinkedCustomHashMap<K, V> extends _LinkedHash<K, V> {
740 final _Equality<K> _equals;
741 final _Hasher<K> _hashCode;
742 _LinkedCustomHashMap(this._equals, this._hashCode);
743
744 int _computeHashCode(var key) {
745 // We force the hash codes to be unsigned 30-bit integers to avoid
746 // issues with problematic keys like '__proto__'. Another option
747 // would be to throw an exception if the hash code isn't a number.
748 return JS('int', '# & 0x3ffffff', _hashCode(key));
749 }
750
751 int _findBucketIndex(var bucket, var key) {
752 if (bucket == null) return -1;
753 int length = JS('int', '#.length', bucket);
754 for (int i = 0; i < length; i++) {
755 LinkedHashMapCell cell = JS('var', '#[#]', bucket, i);
756 if (_equals(cell._key, key)) return i;
757 }
758 return -1;
759 }
705 } 760 }
706 761
707 class LinkedHashMapCell { 762 class LinkedHashMapCell {
708 final _key; 763 final _key;
709 var _value; 764 var _value;
710 765
711 LinkedHashMapCell _next; 766 LinkedHashMapCell _next;
712 LinkedHashMapCell _previous; 767 LinkedHashMapCell _previous;
713 768
714 LinkedHashMapCell(this._key, this._value); 769 LinkedHashMapCell(this._key, this._value);
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after
1373 } else if (_cell == null) { 1428 } else if (_cell == null) {
1374 _current = null; 1429 _current = null;
1375 return false; 1430 return false;
1376 } else { 1431 } else {
1377 _current = _cell._element; 1432 _current = _cell._element;
1378 _cell = _cell._next; 1433 _cell = _cell._next;
1379 return true; 1434 return true;
1380 } 1435 }
1381 } 1436 }
1382 } 1437 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698