 Chromium Code Reviews
 Chromium Code Reviews Issue 11567018:
  Get rid of the polyfill identity set implementation in favour of a  (Closed) 
  Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart
    
  
    Issue 11567018:
  Get rid of the polyfill identity set implementation in favour of a  (Closed) 
  Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart| Index: pkg/serialization/lib/src/serialization_helpers.dart | 
| diff --git a/pkg/serialization/lib/src/serialization_helpers.dart b/pkg/serialization/lib/src/serialization_helpers.dart | 
| index df4b2cf285d0c38e28de414868e61c494b9f21f8..9423afe35ce783a0e043bbb1b9687b2155defe35 100644 | 
| --- a/pkg/serialization/lib/src/serialization_helpers.dart | 
| +++ b/pkg/serialization/lib/src/serialization_helpers.dart | 
| @@ -8,7 +8,6 @@ | 
| * available in the core library. | 
| */ | 
| library serialization_helpers; | 
| -import 'polyfill_identity_set.dart'; | 
| /** | 
| * A named function of one argument that just returns it. Useful for using | 
| @@ -39,6 +38,12 @@ List sorted(aCollection) { | 
| return result; | 
| } | 
| +/** Helper function for PrimitiveRule to tell which objects it applies to. */ | 
| +bool isPrimitive(object) { | 
| + return identical(object, null) || object is num || object is String || | 
| + identical(object, true) || identical(object, false); | 
| +} | 
| + | 
| /** | 
| * Be able to iterate polymorphically between List-like and Map-like things. | 
| * For example, keysAndValues(["a", "b", "c"]).forEach((key, value) => ...); | 
| @@ -167,39 +172,75 @@ class _Sentinel { | 
| } | 
| /** | 
| - * This provides an identity map which allows true, false, and null as | 
| - * valid keys. It does this by special casing them and using some other | 
| - * known object as the key instead. | 
| + * This provides an identity map which also allows true, false, and null | 
| + * as valid keys. In the interests of avoiding duplicating map code, and | 
| + * because hashCode for arbitrary objects is currently very slow on the VM, | 
| + * just do a linear lookup. | 
| */ | 
| -class IdentityMapPlus<K, V> extends IdentityMap { | 
| - final trueish = const _Sentinel(true); | 
| - final falseish = const _Sentinel(false); | 
| - final nullish = const _Sentinel(null); | 
| - | 
| - wrap(x) { | 
| - if (x == true) return trueish; | 
| - if (x == false) return falseish; | 
| - if (x == null) return nullish; | 
| - return x; | 
| +class IdentityMap<K, V> implements Map<K, V> { | 
| + | 
| + List<K> keys = <K>[]; | 
| + List<V> values = <V>[]; | 
| + | 
| + V operator [](K key) { | 
| + var index = _indexOf(key); | 
| + return (index == -1) ? null : values[index]; | 
| } | 
| - unwrap(x) { | 
| - if (x is _Sentinel) return x._wrappedObject; | 
| - return x; | 
| + void operator []=(K key, V value) { | 
| + var index = _indexOf(key); | 
| + if (index == -1) { | 
| + keys.add(key); | 
| + values.add(value); | 
| + } else { | 
| + values[index] = value; | 
| + } | 
| } | 
| - operator [](key) => super[wrap(key)]; | 
| - operator []=(key, value) => super[wrap(key)] = value; | 
| + putIfAbsent(K key, Function ifAbsent) { | 
| + var index = _indexOf(key); | 
| + if (index == -1) { | 
| + keys.add(key); | 
| + values.add(ifAbsent()); | 
| + return values.last; | 
| + } else { | 
| + return values[index]; | 
| + } | 
| + } | 
| - putIfAbsent(key, ifAbsent) => super.putIfAbsent(wrap(key), ifAbsent); | 
| + _indexOf(K key) { | 
| + // Go backwards on the guess that we are most likely to access the most | 
| + // recently added. | 
| + // Make strings and primitives unique | 
| + var compareEquality = isPrimitive(key); | 
| + for (var i = keys.length - 1; i >= 0; i--) { | 
| + var equal = compareEquality ? key == keys[i] : identical(key, keys[i]); | 
| + if (equal) return i; | 
| + } | 
| + return -1; | 
| + } | 
| - containsKey(key) => super.containsKey(wrap(key)); | 
| - forEach(f) => super.forEach((key, value) => f(unwrap(key), value)); | 
| - remove(key) => super.remove(unwrap(key)); | 
| - /** | 
| - * Note that keys is a very inefficient operation for this type. Don't do it. | 
| - */ | 
| - get keys => super.keys.map((x) => unwrap(x)); | 
| -} | 
| + bool containsKey(K key) => _indexOf(key) != -1; | 
| + void forEach(f(K key, V value)) { | 
| + for (var i = 0; i < keys.length; i++) { | 
| + f(keys[i], values[i]); | 
| + } | 
| + } | 
| + | 
| + V remove(K key) { | 
| + var index = _indexOf(key); | 
| + if (index == -1) return null; | 
| + keys.removeAt(index); | 
| + return values.removeAt(index); | 
| + } | 
| + int get length => keys.length; | 
| + void clear() { | 
| + keys = <K>[]; | 
| 
Jennifer Messerly
2012/12/17 19:29:53
perhaps:
keys.clear();
values.clear(); ?
then ke
 
Alan Knight
2012/12/17 21:15:27
Nice. Done.
 | 
| + values = <V>[]; | 
| + } | 
| + bool get isEmpty => keys.isEmpty; | 
| + // Note that this is doing an equality comparison. | 
| + bool containsValue(x) => values.contains(x); | 
| +} |