Index: sdk/lib/core/uri.dart |
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart |
index c8277e7fc6b4b035ad7624e195049d0817a80740..f536c97936be5e08ed8513f206f225223f7a508c 100644 |
--- a/sdk/lib/core/uri.dart |
+++ b/sdk/lib/core/uri.dart |
@@ -82,6 +82,16 @@ class Uri { |
final String fragment; |
/** |
+ * Cache the computed return value of [pathSegements]. |
+ */ |
+ List<String> _pathSegments; |
+ |
+ /** |
+ * Cache the computed return value of [queryParameters]. |
+ */ |
+ Map<String, String> _queryParameters; |
+ |
+ /** |
* Creates a new URI object by parsing a URI string. |
*/ |
static Uri parse(String uri) => new Uri._fromMatch(_splitRe.firstMatch(uri)); |
@@ -167,10 +177,19 @@ class Uri { |
* Returns the URI path split into its segments. Each of the |
* segments in the returned list have been decoded. If the path is |
* empty the empty list will be returned. |
+ * |
+ * The returned list is immutable and will throw [StateError] on any |
+ * calls that would mutate it. |
*/ |
List<String> get pathSegments { |
- if (path == "") return const<String>[]; |
- return path.split("/").map(Uri.decodeComponent).toList(growable: false); |
+ if (_pathSegments == null) { |
+ _pathSegments = new _ImmutableList( |
+ path == "" ? const<String>[] |
+ : path.split("/") |
+ .map(Uri.decodeComponent) |
+ .toList(growable: false)); |
+ } |
+ return _pathSegments; |
} |
/* |
@@ -178,9 +197,14 @@ class Uri { |
* specified for FORM post in the HTML 4.01 specification. Each key |
* and value in the returned map have been decoded. If there is no |
* query the empty map will be returned. |
+ * |
+ * The returned map is immutable and will throw [StateError] on any |
+ * calls that would mutate it. |
*/ |
Map<String, String> get queryParameters { |
- return query.split("&").fold({}, (map, element) { |
+ if (_queryParameters == null) { |
+ var map; |
+ map = query.split("&").fold({}, (map, element) { |
int index = element.indexOf("="); |
if (index == -1) { |
if (!element.isEmpty) map[element] = ""; |
@@ -190,7 +214,10 @@ class Uri { |
map[Uri.decodeQueryComponent(key)] = decodeQueryComponent(value); |
} |
return map; |
- }); |
+ }); |
+ _queryParameters = new _ImmutableMap(map); |
+ } |
+ return _queryParameters; |
} |
static String _makeScheme(String scheme) { |
@@ -944,3 +971,70 @@ class Uri { |
// pqrstuvwxyz ~ |
0x47ff]; // 0x70 - 0x7f 1111111111100010 |
} |
+ |
Lasse Reichstein Nielsen
2013/06/03 07:54:27
dart:collections has an UnmodifiableListView you c
Søren Gjesse
2013/06/03 09:18:15
Thanks - I missed that.
|
+class _ImmutableList<E> implements List<E> { |
+ final List _list; |
+ const _ImmutableList(this._list); |
+ |
+ E operator [](int index) => _list[index]; |
+ void operator []=(int index, E value) { |
+ throw new StateError("Immutable list"); |
+ } |
+ int get length => _list.length; |
+ void set length(int newLength) => throw new StateError("Immutable list"); |
+ void add(E value) => throw new StateError("Immutable list"); |
+ void addAll(Iterable<E> iterable) => throw new StateError("Immutable list"); |
+ Iterable<E> get reversed => _list.reversed; |
+ void sort([int compare(E a, E b)]) => throw new StateError("Immutable list"); |
+ int indexOf(E element, [int start = 0]) => _list.indexOf(element, start); |
+ int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start); |
+ void clear() => throw new StateError("Immutable list"); |
+ void insert(int index, E element) => throw new StateError("Immutable list"); |
+ void insertAll(int index, Iterable<E> iterable) { |
+ throw new StateError("Immutable list"); |
+ } |
+ void setAll(int index, Iterable<E> iterable) { |
+ throw new StateError("Immutable list"); |
+ } |
+ bool remove(Object value) => throw new StateError("Immutable list"); |
+ E removeAt(int index) => throw new StateError("Immutable list"); |
+ E removeLast() => throw new StateError("Immutable list"); |
+ void removeWhere(bool test(E element)) { |
+ throw new StateError("Immutable list"); |
+ } |
+ void retainWhere(bool test(E element)) { |
+ throw new StateError("Immutable list"); |
+ } |
+ List<E> sublist(int start, [int end]) => _list.sublist(start, end); |
+ Iterable<E> getRange(int start, int end) => _list.getRange(start, end); |
+ void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { |
+ throw new StateError("Immutable list"); |
+ } |
+ void removeRange(int start, int end) => throw new StateError("Immutable list"); |
+ void fillRange(int start, int end, [E fillValue]) { |
+ throw new StateError("Immutable list"); |
+ } |
+ void replaceRange(int start, int end, Iterable<E> iterable) { |
+ throw new StateError("Immutable list"); |
+ } |
+ Map<int, E> asMap() => _list.asMap(); |
+} |
+ |
+class _ImmutableMap<K, V> implements Map<K, V> { |
Lasse Reichstein Nielsen
2013/06/03 07:54:27
No UnmodifiableMapView, sorry :(
We probably shoul
Søren Gjesse
2013/06/03 09:18:15
OK, keeping this (renaming to _UnmodifiableMap).
|
+ final Map _map; |
+ const _ImmutableMap(this._map); |
+ |
+ bool containsValue(V value) => _map.containsValue(value); |
+ bool containsKey(K key) => _map.containsKey(key); |
+ V operator [](K key) => _map[key]; |
+ void operator []=(K key, V value) => throw new StateError("Immutable map"); |
Lasse Reichstein Nielsen
2013/06/03 07:54:27
UnsupportedError
Søren Gjesse
2013/06/03 09:18:15
Done.
|
+ V putIfAbsent(K key, V ifAbsent()) => throw new StateError("Immutable map"); |
+ V remove(K key) => throw new StateError("Immutable map"); |
+ void clear() => throw new StateError("Immutable map"); |
+ void forEach(void f(K key, V value)) => _map.forEach(f); |
+ Iterable<K> get keys => _map.keys; |
+ Iterable<V> get values => _map.values; |
+ int get length => _map.length; |
+ bool get isEmpty => _map.isEmpty; |
+ bool get isNotEmpty => _map.isNotEmpty; |
+} |