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

Unified Diff: dart/sdk/lib/_internal/lib/js_mirrors.dart

Issue 22831004: Collections returned by mirror API should be unmodifiable. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/sdk/lib/_internal/lib/js_mirrors.dart
diff --git a/dart/sdk/lib/_internal/lib/js_mirrors.dart b/dart/sdk/lib/_internal/lib/js_mirrors.dart
index 7beac1b977276fdc35186a881791421081fa0cfa..75692929eecab7d1ccf15262480cb5794d24c489 100644
--- a/dart/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/dart/sdk/lib/_internal/lib/js_mirrors.dart
@@ -5,6 +5,7 @@
library dart._js_mirrors;
import 'dart:async';
+import 'dart:collection' show UnmodifiableListView;
import 'dart:mirrors';
import 'dart:_foreign_helper' show
@@ -40,6 +41,8 @@ String getName(Symbol symbol) {
}
class JsMirrorSystem implements MirrorSystem {
+ UnmodifiableMapView<Uri, LibraryMirror> _cachedLibraries;
+
final IsolateMirror isolate = new JsIsolateMirror();
TypeMirror get dynamicType => _dynamicType;
@@ -53,17 +56,20 @@ class JsMirrorSystem implements MirrorSystem {
computeLibrariesByName();
Map<Uri, LibraryMirror> get libraries {
- Map<Uri, LibraryMirror> result = new Map<Uri, LibraryMirror>();
+ if (_cachedLibraries != null) return _cachedLibraries;
+ Map<Uri, LibraryMirror> result = new Map();
for (List<LibraryMirror> list in librariesByName.values) {
for (LibraryMirror library in list) {
result[library.uri] = library;
}
}
- return result;
+ return _cachedLibraries =
+ new UnmodifiableMapView<Uri, LibraryMirror>(result);
}
Iterable<LibraryMirror> findLibrary(Symbol libraryName) {
- return new List<LibraryMirror>.from(librariesByName[n(libraryName)]);
+ return new UnmodifiableListView<LibraryMirror>(
+ librariesByName[n(libraryName)]);
}
static Map<String, List<LibraryMirror>> computeLibrariesByName() {
@@ -188,6 +194,13 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
final bool _isRoot;
List<JsMethodMirror> _cachedFunctionMirrors;
List<JsVariableMirror> _cachedFields;
+ UnmodifiableMapView<Symbol, ClassMirror> _cachedClasses;
+ UnmodifiableMapView<Symbol, MethodMirror> _cachedFunctions;
+ UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters;
+ UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters;
+ UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables;
+ UnmodifiableMapView<Symbol, Mirror> _cachedMembers;
+ UnmodifiableListView<InstanceMirror> _cachedMetadata;
JsLibraryMirror(Symbol simpleName,
this.uri,
@@ -205,13 +218,15 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
List<JsMethodMirror> get _methods => _functionMirrors;
Map<Symbol, ClassMirror> get classes {
- var result = new Map<Symbol, ClassMirror>();
+ if (_cachedClasses != null) return _cachedClasses;
+ var result = new Map();
for (String className in _classes) {
JsClassMirror cls = reflectClassByMangledName(className);
result[cls.simpleName] = cls;
cls._owner = this;
}
- return result;
+ return _cachedClasses =
+ new UnmodifiableMapView<Symbol, ClassMirror>(result);
}
InstanceMirror setField(Symbol fieldName, Object arg) {
@@ -293,40 +308,48 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
var result = <VariableMirror>[];
parseCompactFieldSpecification(
this, _compactFieldSpecification, true, result);
- _cachedFields = result;
- return _cachedFields;
+ return _cachedFields = result;
}
Map<Symbol, MethodMirror> get functions {
- var result = new Map<Symbol, MethodMirror>();
+ if (_cachedFunctions != null) return _cachedFunctions;
+ var result = new Map();
for (JsMethodMirror mirror in _functionMirrors) {
if (!mirror.isConstructor) result[mirror.simpleName] = mirror;
}
- return result;
+ return _cachedFunctions =
+ new UnmodifiableMapView<Symbol, MethodMirror>(result);
}
Map<Symbol, MethodMirror> get getters {
- var result = new Map<Symbol, MethodMirror>();
+ if (_cachedGetters != null) return _cachedGetters;
+ var result = new Map();
// TODO(ahe): Implement this.
- return result;
+ return _cachedGetters =
+ new UnmodifiableMapView<Symbol, MethodMirror>(result);
}
Map<Symbol, MethodMirror> get setters {
- var result = new Map<Symbol, MethodMirror>();
+ if (_cachedSetters != null) return _cachedSetters;
+ var result = new Map();
// TODO(ahe): Implement this.
- return result;
+ return _cachedSetters =
+ new UnmodifiableMapView<Symbol, MethodMirror>(result);
}
Map<Symbol, VariableMirror> get variables {
- var result = new Map<Symbol, VariableMirror>();
+ if (_cachedVariables != null) return _cachedVariables;
+ var result = new Map();
for (JsVariableMirror mirror in _fields) {
result[mirror.simpleName] = mirror;
}
- return result;
+ return _cachedVariables =
+ new UnmodifiableMapView<Symbol, VariableMirror>(result);
}
Map<Symbol, Mirror> get members {
- Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(classes);
+ if (_cachedMembers != null) return _cachedMembers;
+ Map<Symbol, Mirror> result = new Map.from(classes);
addToResult(Symbol key, Mirror value) {
result[key] = value;
}
@@ -334,12 +357,14 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
getters.forEach(addToResult);
setters.forEach(addToResult);
variables.forEach(addToResult);
- return result;
+ return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(result);
}
List<InstanceMirror> get metadata {
+ if (_cachedMetadata != null) return _cachedMetadata;
preserveMetadata();
- return _metadata.map(reflect).toList();
+ return _cachedMetadata =
+ new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect));
}
// TODO(ahe): Test this getter.
@@ -511,6 +536,13 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
JsClassMirror _superclass;
List<JsMethodMirror> _cachedMethods;
List<JsVariableMirror> _cachedFields;
+ UnmodifiableMapView<Symbol, MethodMirror> _cachedConstructors;
+ UnmodifiableMapView<Symbol, MethodMirror> _cachedMethodsMap;
+ UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters;
+ UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters;
+ UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables;
+ UnmodifiableMapView<Symbol, Mirror> _cachedMembers;
+ UnmodifiableListView<InstanceMirror> _cachedMetadata;
// Set as side-effect of accessing JsLibraryMirror.classes.
JsLibraryMirror _owner;
@@ -533,13 +565,15 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
}
Map<Symbol, MethodMirror> get constructors {
- var result = new Map<Symbol, MethodMirror>();
+ if (_cachedConstructors != null) return _cachedConstructors;
+ var result = new Map();
for (JsMethodMirror method in _methods) {
if (method.isConstructor) {
result[method.simpleName] = method;
}
}
- return result;
+ return _cachedConstructors =
+ new UnmodifiableMapView<Symbol, MethodMirror>(result);
}
List<JsMethodMirror> get _methods {
@@ -618,20 +652,23 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
}
Map<Symbol, MethodMirror> get methods {
- var result = new Map<Symbol, MethodMirror>();
+ if (_cachedMethodsMap != null) return _cachedMethodsMap;
+ var result = new Map();
for (JsMethodMirror method in _methods) {
if (!method.isConstructor && !method.isGetter && !method.isSetter) {
result[method.simpleName] = method;
}
}
- return result;
+ return _cachedMethodsMap =
+ new UnmodifiableMapView<Symbol, MethodMirror>(result);
}
Map<Symbol, MethodMirror> get getters {
+ if (_cachedGetters != null) return _cachedGetters;
// TODO(ahe): This is a hack to remove getters corresponding to a field.
var fields = variables;
- var result = new Map<Symbol, MethodMirror>();
+ var result = new Map();
for (JsMethodMirror method in _methods) {
if (method.isGetter) {
@@ -641,14 +678,16 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
result[method.simpleName] = method;
}
}
- return result;
+ return _cachedGetters =
+ new UnmodifiableMapView<Symbol, MethodMirror>(result);
}
Map<Symbol, MethodMirror> get setters {
+ if (_cachedSetters != null) return _cachedSetters;
// TODO(ahe): This is a hack to remove setters corresponding to a field.
var fields = variables;
- var result = new Map<Symbol, MethodMirror>();
+ var result = new Map();
for (JsMethodMirror method in _methods) {
if (method.isSetter) {
@@ -660,19 +699,23 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
result[method.simpleName] = method;
}
}
- return result;
+ return _cachedSetters =
+ new UnmodifiableMapView<Symbol, MethodMirror>(result);
}
Map<Symbol, VariableMirror> get variables {
- var result = new Map<Symbol, VariableMirror>();
+ if (_cachedVariables != null) return _cachedVariables;
+ var result = new Map();
for (JsVariableMirror mirror in _fields) {
result[mirror.simpleName] = mirror;
}
- return result;
+ return _cachedVariables =
+ new UnmodifiableMapView<Symbol, VariableMirror>(result);
}
Map<Symbol, Mirror> get members {
- Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(variables);
+ if (_cachedMembers != null) return _cachedMembers;
+ Map<Symbol, Mirror> result = new Map.from(variables);
for (JsMethodMirror method in _methods) {
if (method.isSetter) {
String name = n(method.simpleName);
@@ -683,7 +726,7 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
// Use putIfAbsent to filter-out getters corresponding to variables.
result.putIfAbsent(method.simpleName, () => method);
}
- return result;
+ return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(result);
}
InstanceMirror setField(Symbol fieldName, Object arg) {
@@ -770,10 +813,12 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
}
List<InstanceMirror> get metadata {
+ if (_cachedMetadata != null) return _cachedMetadata;
if (_metadata == null) {
_metadata = extractMetadata(JS('', '#.prototype', _jsConstructor));
}
- return _metadata.map(reflect).toList();
+ return _cachedMetadata =
+ new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect));
}
ClassMirror get superclass {
@@ -974,7 +1019,7 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
DeclarationMirror _owner;
List _metadata;
var _returnType;
- var _parameters;
+ UnmodifiableListView<ParameterMirror> _parameters;
JsMethodMirror(Symbol simpleName,
this._jsFunction,
@@ -1016,8 +1061,9 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
String get _prettyName => 'MethodMirror';
List<ParameterMirror> get parameters {
+ if (_parameters != null) return _parameters;
metadata; // Compute _parameters as a side-effect of extracting metadata.
- return new List<ParameterMirror>.from(_parameters);
+ return _parameters;
}
DeclarationMirror get owner => _owner;
@@ -1030,19 +1076,26 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
List<InstanceMirror> get metadata {
if (_metadata == null) {
var raw = extractMetadata(_jsFunction);
- _returnType = raw[0];
- int parameterLength = 1 + _parameterCount * 2;
- var formals = new List<ParameterMirror>(_parameterCount);
- int formalsCount = 0;
- for (int i = 1; i < parameterLength; i += 2) {
- var name = raw[i];
- var type = raw[i + 1];
- formals[formalsCount++] = new JsParameterMirror(name, this, type);
+ var formals = new List(_parameterCount);
+ if (!raw.isEmpty) {
+ _returnType = raw[0];
+ int parameterLength = 1 + _parameterCount * 2;
+ int formalsCount = 0;
+ for (int i = 1; i < parameterLength; i += 2) {
+ var name = raw[i];
+ var type = raw[i + 1];
+ formals[formalsCount++] = new JsParameterMirror(name, this, type);
+ }
+ raw = raw.sublist(parameterLength);
+ } else {
+ for (int i = 0; i < _parameterCount; i++) {
+ formals[i] = new JsParameterMirror('argument$i', this, null);
+ }
}
- _parameters = formals;
- _metadata = raw.sublist(parameterLength);
+ _parameters = new UnmodifiableListView<ParameterMirror>(formals);
+ _metadata = new UnmodifiableListView(raw.map(reflect));
}
- return _metadata.map(reflect).toList();
+ return _metadata;
}
Symbol get constructorName {
@@ -1222,3 +1275,43 @@ bool isOperatorName(String name) {
return false;
}
}
+
+// Copied from package "unmodifiable_collection".
+// TODO(ahe): Lobby to get it added to dart:collection.
+class UnmodifiableMapView<K, V> implements Map<K, V> {
+ Map<K, V> _source;
+ UnmodifiableMapView(Map<K, V> source) : _source = source;
+
+ static void _throw() {
+ throw new UnsupportedError("Cannot modify an unmodifiable Map");
+ }
+
+ int get length => _source.length;
+
+ bool get isEmpty => _source.isEmpty;
+
+ bool get isNotEmpty => _source.isNotEmpty;
+
+ V operator [](K key) => _source[key];
+
+ bool containsKey(K key) => _source.containsKey(key);
+
+ bool containsValue(V value) => _source.containsValue(value);
+
+ void forEach(void f(K key, V value)) => _source.forEach(f);
+
+ Iterable<K> get keys => _source.keys;
+
+ Iterable<V> get values => _source.values;
+
+
+ void operator []=(K key, V value) => _throw();
+
+ V putIfAbsent(K key, V ifAbsent()) { _throw(); }
kustermann 2013/08/12 17:07:01 Why do you use once {} and once => ?
ahe 2013/08/12 17:10:21 I don't know, this is a verbatim copy from the pac
+
+ void addAll(Map<K, V> other) => _throw();
+
+ V remove(K key) { _throw(); }
+
+ void clear() => _throw();
+}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698