blob: 398d37cf339db2f1e8d8035d6f7d6c5a569b1996 [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of _js_helper;
abstract class ConstantMap<K, V> implements Map<K, V> {
bool get isEmpty => length == 0;
bool get isNotEmpty => !isEmpty;
String toString() => Maps.mapToString(this);
_throwUnmodifiable() {
throw new UnsupportedError("Cannot modify unmodifiable Map");
}
void operator []=(K key, V val) => _throwUnmodifiable();
V putIfAbsent(K key, V ifAbsent()) => _throwUnmodifiable();
V remove(K key) => _throwUnmodifiable();
void clear() => _throwUnmodifiable();
void addAll(Map<K, V> other) => _throwUnmodifiable();
}
// This class has no constructor. This is on purpose since the instantiation
// is shortcut by the compiler.
class ConstantStringMap<K, V> extends ConstantMap<K, V>
implements _symbol_dev.EfficientLength {
final int length;
// A constant map is backed by a JavaScript object.
final _jsObject;
final List<K> _keys;
bool containsValue(V needle) {
return values.any((V value) => value == needle);
}
bool containsKey(Object key) {
if (key is! String) return false;
if (key == '__proto__') return false;
return jsHasOwnProperty(_jsObject, key);
}
V operator [](Object key) {
if (key is! String) return null;
if (!containsKey(key)) return null;
return jsPropertyAccess(_jsObject, key);
}
void forEach(void f(K key, V value)) {
_keys.forEach((key) => f(key, this[key]));
}
Iterable<K> get keys {
return new _ConstantMapKeyIterable<K>(this);
}
Iterable<V> get values {
return new MappedIterable<K, V>(_keys, (key) => this[key]);
}
}
// This class has no constructor. This is on purpose since the instantiation
// is shortcut by the compiler.
class ConstantProtoMap<K, V> extends ConstantStringMap<K, V> {
final V _protoValue;
bool containsKey(Object key) {
if (key == '__proto__') return true;
return super.containsKey(key);
}
V operator [](Object key) {
if (key == '__proto__') return _protoValue;
return super[key];
}
}
class _ConstantMapKeyIterable<K> extends IterableBase<K> {
ConstantStringMap<K, dynamic> _map;
_ConstantMapKeyIterable(this._map);
Iterator<K> get iterator => _map._keys.iterator;
}
// This class has no constructor. This is on purpose since the instantiation
// is shortcut by the compiler.
class GeneralConstantMap<K, V> extends ConstantMap<K, V> {
// [_jsData] holds a key-value pair list.
final _jsData;
// We cannot create the backing map on creation since hashCode interceptors
// have not been defined when constants are created.
Map<K, V> _getMap() {
if (JS('bool', r'!this.$map')) {
Map backingMap =
new LinkedHashMap<K, V>(equals: identical, hashCode: objectHashCode);
JS('', r'this.$map = #', fillLiteralMap(_jsData, backingMap));
}
return JS('Map', r'this.$map');
}
bool containsValue(V needle) {
return _getMap().containsValue(needle);
}
bool containsKey(Object key) {
return _getMap().containsKey(key);
}
V operator [](Object key) {
return _getMap()[key];
}
void forEach(void f(K key, V value)) {
_getMap().forEach(f);
}
Iterable<K> get keys {
return _getMap().keys;
}
Iterable<V> get values {
return _getMap().values;
}
int get length => _getMap().length;
}