| Index: tool/input_sdk/private/constant_map.dart
|
| diff --git a/tool/input_sdk/private/constant_map.dart b/tool/input_sdk/private/constant_map.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1c16860a647b77118982dbdf0d9b3f0c4215ce90
|
| --- /dev/null
|
| +++ b/tool/input_sdk/private/constant_map.dart
|
| @@ -0,0 +1,192 @@
|
| +// 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 dart._js_helper;
|
| +
|
| +class ConstantMapView<K, V> extends UnmodifiableMapView<K, V>
|
| + implements ConstantMap<K, V> {
|
| + ConstantMapView(Map<K, V> base) : super(base);
|
| +}
|
| +
|
| +abstract class ConstantMap<K, V> implements Map<K, V> {
|
| + // Used to create unmodifiable maps from other maps.
|
| + factory ConstantMap.from(Map other) {
|
| + List keys = other.keys.toList();
|
| + bool allStrings = true;
|
| + for (var k in keys) {
|
| + if (k is! String) {
|
| + allStrings = false;
|
| + break;
|
| + }
|
| + }
|
| + if (allStrings) {
|
| + bool containsProto = false;
|
| + var protoValue = null;
|
| + var object = JS('=Object', '{}');
|
| + int length = 0;
|
| + for (var k in keys) {
|
| + var v = other[k];
|
| + if (k != "__proto__") {
|
| + if (!jsHasOwnProperty(object, k as String)) length++;
|
| + JS("void", "#[#] = #", object, k, v);
|
| + } else {
|
| + containsProto = true;
|
| + protoValue = v;
|
| + }
|
| + }
|
| + if (containsProto) {
|
| + length++;
|
| + return new ConstantProtoMap<K, V>._(length, object, keys, protoValue);
|
| + }
|
| + return new ConstantStringMap<K, V>._(length, object, keys);
|
| + }
|
| + // TODO(lrn): Make a proper unmodifiable map implementation.
|
| + return new ConstantMapView<K, V>(new Map.from(other));
|
| + }
|
| +
|
| + const ConstantMap._();
|
| +
|
| + bool get isEmpty => length == 0;
|
| +
|
| + bool get isNotEmpty => !isEmpty;
|
| +
|
| + String toString() => Maps.mapToString(this);
|
| +
|
| + static _throwUnmodifiable() {
|
| + throw new UnsupportedError("Cannot modify unmodifiable Map");
|
| + }
|
| + void operator []=(K key, V val) => _throwUnmodifiable();
|
| + V putIfAbsent(K key, V ifAbsent()) => _throwUnmodifiable();
|
| + V remove(Object key) => _throwUnmodifiable();
|
| + void clear() => _throwUnmodifiable();
|
| + void addAll(Map<K, V> other) => _throwUnmodifiable();
|
| +}
|
| +
|
| +class ConstantStringMap<K, V> extends ConstantMap<K, V> {
|
| +
|
| + // This constructor is not used for actual compile-time constants.
|
| + // The instantiation of constant maps is shortcut by the compiler.
|
| + const ConstantStringMap._(this._length, this._jsObject, this._keys)
|
| + : super._();
|
| +
|
| + // TODO(18131): Ensure type inference knows the precise types of the fields.
|
| + final int _length;
|
| + // A constant map is backed by a JavaScript object.
|
| + final _jsObject;
|
| + final List<K> _keys;
|
| +
|
| + int get length => JS('JSUInt31', '#', _length);
|
| + List get _keysArray => JS('JSUnmodifiableArray', '#', _keys);
|
| +
|
| + bool containsValue(Object needle) {
|
| + return values.any((V value) => value == needle);
|
| + }
|
| +
|
| + bool containsKey(Object key) {
|
| + if (key is! String) return false;
|
| + if ('__proto__' == key) return false;
|
| + return jsHasOwnProperty(_jsObject, key);
|
| + }
|
| +
|
| + V operator [](Object key) {
|
| + if (!containsKey(key)) return null;
|
| + return _fetch(key);
|
| + }
|
| +
|
| + // [_fetch] is the indexer for keys for which `containsKey(key)` is true.
|
| + _fetch(key) => jsPropertyAccess(_jsObject, key);
|
| +
|
| + void forEach(void f(K key, V value)) {
|
| + // Use a JS 'cast' to get efficient loop. Type inferrence doesn't get this
|
| + // since constant map representation is chosen after type inferrence and the
|
| + // instantiation is shortcut by the compiler.
|
| + var keys = _keysArray;
|
| + for (int i = 0; i < keys.length; i++) {
|
| + var key = keys[i];
|
| + f(key, _fetch(key));
|
| + }
|
| + }
|
| +
|
| + Iterable<K> get keys {
|
| + return new _ConstantMapKeyIterable<K>(this);
|
| + }
|
| +
|
| + Iterable<V> get values {
|
| + return new MappedIterable<K, V>(_keysArray, (key) => _fetch(key));
|
| + }
|
| +}
|
| +
|
| +class ConstantProtoMap<K, V> extends ConstantStringMap<K, V> {
|
| + // This constructor is not used. The instantiation is shortcut by the
|
| + // compiler. It is here to make the uninitialized final fields legal.
|
| + ConstantProtoMap._(length, jsObject, keys, this._protoValue)
|
| + : super._(length, jsObject, keys);
|
| +
|
| + final V _protoValue;
|
| +
|
| + bool containsKey(Object key) {
|
| + if (key is! String) return false;
|
| + if ('__proto__' == key) return true;
|
| + return jsHasOwnProperty(_jsObject, key);
|
| + }
|
| +
|
| + _fetch(key) =>
|
| + '__proto__' == key ? _protoValue : jsPropertyAccess(_jsObject, key);
|
| +}
|
| +
|
| +class _ConstantMapKeyIterable<K> extends Iterable<K> {
|
| + ConstantStringMap<K, dynamic> _map;
|
| + _ConstantMapKeyIterable(this._map);
|
| +
|
| + Iterator<K> get iterator => _map._keysArray.iterator;
|
| +
|
| + int get length => _map._keysArray.length;
|
| +}
|
| +
|
| +class GeneralConstantMap<K, V> extends ConstantMap<K, V> {
|
| + // This constructor is not used. The instantiation is shortcut by the
|
| + // compiler. It is here to make the uninitialized final fields legal.
|
| + GeneralConstantMap(this._jsData) : super._();
|
| +
|
| + // [_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() {
|
| + LinkedHashMap<K, V> backingMap = JS('LinkedHashMap|Null', r'#.$map', this);
|
| + if (backingMap == null) {
|
| + backingMap = new JsLinkedHashMap<K, V>();
|
| + fillLiteralMap(_jsData, backingMap);
|
| + JS('', r'#.$map = #', this, backingMap);
|
| + }
|
| + return backingMap;
|
| + }
|
| +
|
| + bool containsValue(Object 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;
|
| +}
|
|
|